1

私は運が悪いので、ウェブを検索してきました。次の Python コードがあります。

class LED(Structure):
_fields_ = [
            ('color', c_char_p),
            ('id', c_uint32)
            ]

class LEDConfiguration(Structure):
_fields_ = [
            ('daemon_user', c_char_p),
            ('leds', POINTER(LED)),
            ('num_leds', c_uint32)
            ]

以下は、これらの構造体を使用して LEDConfiguration を返す単純化された関数の例です。

def parseLedConfiguration(path, board):
lc = LEDConfiguration()
for config in configs:
    if( config.attributes['ID'].value.lstrip().rstrip() == board ):
        lc.daemon_user = c_char_p('some_name')
        leds = []
        #Imagine this in a loop
        ld = LED()
        ld.color = c_char_p('red')
        ld.id = int(0)
        leds.append(ld)
        #end imagined loop

        lc.num_leds = len(leds)
        lc.leds = (LED * len(leds))(*leds)

return lc

これが私が使用しているCコードです(Pythonのセットアップ/「parseLedConfiguration」関数の呼び出しなどに関連するすべてを取り除きましたが、役立つ場合は追加できます)。

        /*Calling the python function "parseLedConfiguration"
          pValue is the returned "LEDConfiguration" python Structure*/

        pValue = PyObject_CallObject(pFunc, pArgs);
        Py_DECREF(pArgs);

        if (pValue != NULL)
        {
            int i, num_leds;
            PyObject *obj = PyObject_GetAttr(pValue, PyString_FromString("daemon_user"));
            daemon_user = PyString_AsString(obj);
            Py_DECREF(obj);

            obj = PyObject_GetAttr(pValue, PyString_FromString("num_leds"));
            num_leds = PyInt_AsLong(obj);
            Py_DECREF(obj);

            obj = PyObject_GetAttr(pValue, PyString_FromString("leds"));
            PyObject_Print(obj, stdout, 0);

私の問題は、最終的な「obj」に返されるものにアクセスする方法を理解することです。「obj」の「PyObject_Print」は、次の出力を示しています。

<ConfigurationParser.LP_LED object at 0x7f678a06fcb0>

上記の「LEDConfiguration」オブジェクトにアクセスするのと同じ方法で、その LP_LED オブジェクトにアクセスできる状態になりたいと考えています。

編集1

おそらくもっと重要な別の質問だと思いますが、私のpythonコードは正しいですか? Python C APIからアクセスできるように、「構造」のリストまたは配列を別の「構造」内に格納する方法はありますか?

ありがとう!

4

1 に答える 1

1

あなたのEDIT1は根本的な質問を明確にしているので、それを一番上に置きましょう。

別のおそらくもっと重要な質問を推測します、私のPythonコードは正しいですか?Python C APIからアクセスできるように、「Structure」のリストまたは配列を別の「Structure」内に格納する方法はそうですか?

いいえ、 Cコードからアクセスできるように、配列をStructure別の配列内に格納する必要があります。Python C APIからアクセスしたい場合は、Pythonを使用してください。Structurenon-Python-C-APIlist

一般に、PythonとCの両方でコードを記述している場合、一方の側だけを後ろに曲げて、もう一方の側で作業する必要があります。Pythonでctypes Structuresやsなどを使用するポイントは、C APIを経由せずに、Cで直接動作できるようにすることです。逆に、のような関数を使用するポイントは、Pythonコードではなく、通常のPythonコードを使用できるようにすることです。POINTERPyList_GetItemctypes

したがって、Python C APIを介してアクセスできるようにlist内部を格納する場合は、Pythonを格納するだけです。そもそも、実際には必要ありません。通常のPythonクラスを使用します(おそらくと)。このコードは、まったくインポートせずに記述できます。StructurelistStructure__slots__ctypes

逆に、Cで直接使用できる構造体を格納する場合は、ctypes;を使用してそれを行うことができます。次に、Cコードでは、構造がすべてCであるため、Python APIが不要StructurePyObject *なります。これは通常、既存のCコードがあり、 Cコードを最初から設計するときではなく、Pythonからインターフェースしますが、他の方法で使用できないという規則はありません。

一方、これが相互に通信するCコードとPythonコードを作成する最初の試みである場合は、を使用することをお勧めしますCython。次に、それに慣れたら、学習したい場合は、Pythonを使用してPythonについてまったく何も知らないCコードと通信するctypes別のプロジェクトを実行します。ctypes次に、C APIを使用して何も知らないPythonコードと通信する3番目のプロジェクトctypes(ほとんどのC拡張モジュールのように)。3つすべてに精通すると、将来のほとんどのプロジェクトに適したものを選択できるようになります。

ここで、特定の問題に答えるために:

まず、PyList_GetItem(またはC APIの他のほとんどの関数)がNULLを返す場合、これは例外があることを意味するため、例外を確認してログに記録する必要があります。設定された例外を見ずにCAPIでNULL戻り値をデバッグしようとすることは、トレースバックを見ずにPythonコードをデバッグしようとすることに似ています。

とにかく、この関数が失敗する可能性がある明らかな理由がいくつかあります。範囲外のインデックスを使用して呼び出している場合や、listまったく機能していないもので呼び出している場合があります。

実際、2番目のものはここではかなり明白に見えます。印刷すると次のようになりobjます。

<ConfigurationParser.LP_LED object at 0x7f678a06fcb0>

次に、(ポインタへの)LEDオブジェクトがあり、LEDオブジェクトはlistsではありません。

そして、あなたがあなたのコードを見ると、少なくともあなたが私たちに見せたコードでは、どこにもオブジェクトlistがないようです。LEDあなたはPOINTER(LED)、C配列で減衰しLEDたsのC配列を保持できる、を持っていますが、それはそれらのPythonと同じものではありませんlist。これは単なるC配列であり、C配列構文を使用して間接参照します。

PyObject *led = ledarray[i];
于 2012-12-12T18:17:12.433 に答える