Pregunta

Desarrollé una DLL para un controlador en C. Escribí un programa de prueba en C ++ y la DLL funciona bien.

Ahora me gustaría interactuar con esta DLL usando Python. He ocultado con éxito la mayoría de las estructuras C definidas por el usuario, pero hay un punto en el que tengo que usar estructuras C. Soy bastante nuevo en Python, así que puedo equivocarme.

Mi enfoque es redefinir algunas estructuras en python usando ctype y luego pasar la variable a mi DLL. Sin embargo, en estas clases tengo una lista enlazada personalizada que contiene tipos recursivos de la siguiente manera

class EthercatDatagram(Structure):
    _fields_ = [("header", EthercatDatagramHeader),
                ("packet_data_length", c_int),
                ("packet_data", c_char_p),
                ("work_count", c_ushort),
                ("next_command", EthercatDatagram)]

Esto falla, porque dentro de EthercatDatagram, EthercatDatagram no está definido, por lo que el analizador devuelve un error.

¿Cómo debo representar esta lista vinculada en Python para que mi DLL la entienda correctamente?

¿Fue útil?

Solución

Es casi seguro que desea declarar next_command como puntero. Tener una estructura que se contenga a sí misma no es posible (en ningún idioma).

Creo que esto es lo que quieres:

class EthercatDatagram(Structure):
    pass
EthercatDatagram._fields_ = [
    ("header", EthercatDatagramHeader),
    ("packet_data_length", c_int),
    ("packet_data", c_char_p),
    ("work_count", c_ushort),
    ("next_command", POINTER(EthercatDatagram))]

Otros consejos

La razón por la cual

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))

no funciona es que la maquinaria que crea los objetos descriptores (vea la fuente de PyCStructType_setattro ) para acceder al atributo next_command se activa solo tras la asignación al _fields_ atributo de la clase. Simplemente agregar el nuevo campo a la lista pasa completamente desapercibido.

Para evitar esta trampa, use siempre una tupla (y no una lista) como el valor del atributo _fields_ : eso dejará en claro que debe asignar un nuevo valor al atributo y no modificarlo en su lugar.

Tendrá que acceder a _fields_ estáticamente después de haberlo creado.

class EthercatDatagram(Structure)
  _fields_ = [...]

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top