11

さて、私はこれを味わうことができるようにこれを終えるのにとても近いです。過去数週間ほど、Cythonを介してC++で記述されたライブラリとインターフェイスするPython拡張機能を作成しようとしてきました。ここの人たちと数人の友人の助けを借りて、私はそこまでの道のりの98%のように感じるものをなんとか手に入れることができました。残っているのはこれだけです。署名されていないshortの配列へのポインターをPythonオブジェクト(できればリスト)に変換する方法を私は一生理解できません。

少し背景がありますが、コールバック関数を設定するライブラリの一部とインターフェイスしようとしています。これは、これで正常に実行されました。

global callbackfunc

ctypedef unsigned short const_ushort "const uint16_t"

ctypedef void (*Function1)(const_ushort *data, unsigned width, unsigned height)

cdef extern from "lib.hpp":
    void SetCallback(Function1)

cdef void cSetCallback(Function1 function):
    SetCallback(function)

cdef void callcallback(const_ushort *data, unsigned width, unsigned height):
    global callbackfunc
    callbackfunc(data,width,height)

cSetCallback(callcallback)

def PySetCallback(callbackFunc):
    global callbackfunc
    callbackfunc = callbackFunc

この問題は関数「callcallback」内で発生し、「'const_ushort*'をPythonオブジェクトに変換できません」というエラーが表示されます。これを回避する最初の試みは、新しいpythonリストを作成し、ループして配列の各要素を次のようにpythonリストに入れることでした。

datalist = []
for i in range(width*height):
    datalist += data[i]

悲しいことに、これは、型を「const const unsigned short」として定義しようとしているコンパイル済みのcythonコードで私を悩ませますが、これは明らかに問題です。

それから私はこれを試しました:

datalist = []
for i in data:
    datalist += i

これにより、「C配列の反復には既知の終了インデックスが必要です」と表示されます。私はC/C ++をほとんど知らないので、これのほとんどは私にはあまり意味がないことに注意してください。

それで、とにかく、そのようなポインタをpythonオブジェクトに変換する効果的な方法はありますか(通常は約57344アイテムであり、これは非常に時間に敏感なので、配列をループするよりも高速です)

編集:もう少し明確にすると、私はコールバックを使用しています。これを呼び出すライブラリ内のC ++関数は、「const uint_16」の配列へのポインターを送信します。そのため、const_ushortをそのように定義しました。そうしないと、型が統一されないためです。ライブラリを変更することはできません。

Edit2:わかったようです。私がしなければならなかったのは、const unsigned shortsの配列ではなく、unsigned shortsの配列として配列を明示的にキャストすることでした。これにより、非定数でインデックスを付けることができました。これを実現するために、私はこのような別のC ++関数を作成しました(他の誰かが私のためにそれを書いた、私はC ++をほとんど知らない):

unsigned short *convert_short(const unsigned short *test){ return const_cast<unsigned short *>(test); }

これにより、クラス内に「 getindex 」関数を作成し、関数に基づいて正しい値を返すことができました。そうですね、Pythonは配列を正しく読み取っているようですが、そうではないので、このケースは閉じているようです。どうもありがとう。

4

2 に答える 2

5
ctypedef unsigned short const_ushort "const uint16_t"

constCコードに表示されるので、意味がtypedef unsigned short const uint16_tありませんconst。(また、標準タイプuint16_tを再定義しますが、そうすべきではありません。)

あなたはより多くの成功を収めることができます

ctypedef unsigned short *ushort_p "ushort_p"

何らかの理由で、CythonはCconstキーワードを認識していないようです。この問題に対処するには、コールバックのラッパーを使用する必要がある場合がありますconst

ポインタをPythonオブジェクトに変換する場合は、ポインタを。でラップしますcdef class。高さと幅はC配列では記録されないため、クラスが高さと幅を記録していることを確認してください。

于 2011-03-11T15:42:04.907 に答える
1

これはあなたが求めているものとはまったく異なりますが、Cython で unsigned short の配列を操作し、Python 側で回答にアクセスできるようにする場合は、Python 側で Numpy ndarray を作成して渡すことができます。 Cython に変換すると、多次元配列とほぼ同じになります。そうすれば、Python のメモリ管理、いくつかの便利なインデックス構文、および Cython での実数配列を扱う速度の両方を得ることができます。

私の Project Euler ソリューションの例を次に示します。

于 2011-03-11T16:33:34.563 に答える