2009-08-04 22 views
8

私はCでドライバのDLLを開発しました。私はC++でテストプログラムを書いていて、DLLは正常に動作します。python ctype再帰的構造

今、私はPythonを使ってこのDLLを掘り下げたいと思います。私は正常にユーザー定義のC構造のほとんどを隠しましたが、C構造を使用する必要がある点が1つあります。私はむしろPythonに新しいので、私は物事を間違って取得することがあります。

私のアプローチは、ctypeを使用してPythonでいくつかの構造体を再定義し、変数を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でどのように表現すればよいですか?

答えて

15

あなたはほぼ確実にポインタとして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))] 
+1

"は(どの言語でも)可能ではありません" - これはc/C++/java形式の構造体やクラスについては当てはまりますが、代数的データ型の言語では単なる可能性ではなく非常に一般的です。例えば'データリストa = Cons a(List a)| MLファミリ言語(ocaml/haskell/SML/etc)のNilである。 – sinelaw

-1

作成した後は、静的に_fields_にアクセスする必要があります。

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

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

これは機能しません。 AttributeError: 'EthercatDatagram'オブジェクトに属性 'next_command'がありません – user9876

+0

正しい答えは、user9876によって投稿されました。 まずクラスを宣言しなければなりません。クラスのインスタンスを実際に使用しようとするとエラーが発生します。 'pass'を指定して、2番目の呼び出しでフィールドを宣言します。それを前方宣言と考えてください。 – bpescatore

0

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

が動作しない理由は、(PyCStructType_setattro機能のソースを参照してください)記述子オブジェクトを作成する機械ということですnext_commandアトリビュートにアクセスするためのアクセス権は、クラスの_fields_アトリビュートに割り当てられたときにのみアクティブにされます。 新しいフィールドをリストに追加するだけでは、まったく気付かれなくなります。

この落とし穴を避けるには、_fields_属性の値として常にタプル(リストではない)を使用します。これにより、属性に新しい値を割り当ててその場所で変更する必要がないことが明確になります。

関連する問題