Question

J'ai développé une DLL pour un pilote en C. J'ai écrit un programme de test en C ++ et la DLL fonctionne correctement.

Maintenant, j'aimerais échanger avec cette DLL à l'aide de Python. J'ai réussi à masquer la plupart des structures C définies par l'utilisateur, mais je dois utiliser des structures C à un moment donné. Je suis plutôt nouveau sur Python, donc je peux me tromper.

Mon approche consiste à redéfinir quelques structures en python à l'aide de ctype puis à transmettre la variable à ma DLL. Cependant, dans ces classes, j’ai une liste de liens personnalisée qui contient les types récursifs suivants:

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

Cela échoue car, dans EthercatDatagram, EthercatDatagram n'étant pas déjà défini, l'analyseur renvoie une erreur.

Comment dois-je représenter cette liste liée en python pour que ma DLL la comprenne correctement?

Était-ce utile?

La solution

Vous voudrez certainement déclarer next_command en tant que pointeur. Avoir une structure qui se contient n'est pas possible (dans aucune langue).

Je pense que c'est ce que vous voulez:

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))]

Autres conseils

La raison pour laquelle

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

ne fonctionne pas, c’est que la machine qui crée les objets descripteurs (voir la source du PyCStructType_setattro ) pour accéder à l'attribut next_command est activé uniquement lors de l'affectation à _fields_ attribut de la classe. Le simple ajout du nouveau champ à la liste passe complètement inaperçu.

Pour éviter ce piège, utilisez toujours un tuple (et non une liste) comme valeur de l'attribut _fields _ : cela indiquera clairement que vous devez attribuer une nouvelle valeur à l'attribut et ne pas le modifier en place.

Vous devrez accéder à _fields _ après l'avoir créé.

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

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top