28

Python で C++ 関数を実装するために ctypes を使用しています。C++ 関数は、配列へのポインターを返す必要があります。残念ながら、Python で配列にアクセスする方法がわかりません。numpy.frombuffer を試しましたが、うまくいきませんでした。任意の数値の配列を返しただけです。明らかに、私はそれを正しく使用していませんでした。サイズ 10 の配列を使用した簡単な例を次に示します。

function.cpp の内容:

extern "C" int* function(){
int* information = new int[10];
for(int k=0;k<10;k++){
    information[k] = k;
}
return information;
}

wrapper.py の内容:

import ctypes
import numpy as np

output = ctypes.CDLL('./library.so').function()

ArrayType = ctypes.c_double*10
array_pointer = ctypes.cast(output, ctypes.POINTER(ArrayType))
print np.frombuffer(array_pointer.contents)

私が使用しているC++ファイルをコンパイルするには:

g++ -c -fPIC function.cpp -o function.o
g++ -shared -Wl,-soname,library.so -o library.so function.o

Python で配列値にアクセスするために私がしなければならないことはありますか?

4

2 に答える 2

25

あなたの python コードは、いくつかのマイナーな変更後に機能します。

import ctypes

f = ctypes.CDLL('./library.so').function
f.restype = ctypes.POINTER(ctypes.c_int * 10)
print [i for i in f().contents] # output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

基本的には次の 2 つの変更があります。

  1. numpy 関連のコードを削除してctypes.cast呼び出す必要がないためです。

  2. に戻り値の型を指定しますctypes.POINTER(ctypes.c_int * 10)

    デフォルトでは、外部関数は C の int 型を返すと想定されているため、目的のポインター型に変更する必要があります。

newところで、 C コードから Python コードに ed 配列を返すことは不適切なようです。誰が、いつメモリを解放しますか? Python コードで配列を作成し、それらを C コードに渡すことをお勧めします。このようにして、Python コードが配列を所有し、それらのスペースを作成して再利用する責任を負うことは明らかです。

于 2013-02-15T10:45:28.277 に答える
24

function.cppint 配列を返しますが、wrapper.pyそれらを double として解釈しようとします。に変更ArrayTypeするctypes.c_int * 10と、動作するはずです。


np.ctypeslib自分の代わりに使う方がおそらく簡単frombufferです。これは次のようになります

import ctypes
from numpy.ctypeslib import ndpointer

lib = ctypes.CDLL('./library.so')
lib.function.restype = ndpointer(dtype=ctypes.c_int, shape=(10,))

res = lib.function()
于 2013-02-15T02:56:40.630 に答える