Python ctype再帰構造
質問
Cでドライバー用のDLLを開発しました。C++でテストプログラムを作成しましたが、DLLは正常に動作します。
今、Pythonを使用してこのDLLを操作したいと思います。ユーザー定義のC構造のほとんどを正常に非表示にしましたが、C構造を使用しなければならない点が1つあります。私はpythonが初めてなので、間違ったことをするかもしれません。
私のアプローチは、Pythonでctypeを使用していくつかの構造を再定義し、変数をDLLに渡すことです。ただし、これらのクラスには、次のような再帰型を含むカスタムリンクリストがあります
class EthercatDatagram(Structure):
_fields_ = [("header", EthercatDatagramHeader),
("packet_data_length", c_int),
("packet_data", c_char_p),
("work_count", c_ushort),
("next_command", EthercatDatagram)]
これは失敗します。これは、EthercatDatagram内ではEthercatDatagramがまだ定義されていないため、パーサーがエラーを返すためです。
DLLが正しく理解できるように、このリンクリストをPythonでどのように表現すればよいですか?
解決
ほとんど確実にnext_commandをポインターとして宣言する必要があります。それ自体を含む構造を持つことは不可能です(どの言語でも)。
これはあなたが望むものだと思います:
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))]
他のヒント
その理由
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
機能しないのは、記述子オブジェクトを作成する機械です( next_command 属性にアクセスするためのrel = "nofollow"> PyCStructType_setattro
関数)は、 _fields_への割り当て時にのみ有効になります
クラスの属性。
リストに新しいフィールドを追加するだけでは、まったく気付かれません。
この落とし穴を避けるには、 _fields _
属性の値として常にタプル(リストではなく)を使用します。これにより、属性に新しい値を割り当てて、その場で変更しないでください。
作成後に _fields _
に静的にアクセスする必要があります。
class EthercatDatagram(Structure)
_fields_ = [...]
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))