1つ以上の入力配列のセットを受け取り、それらを処理し、その出力を出力配列のセットに書き込むC関数があると仮定します。シグニチャは次のようになります(count
処理される配列要素の数を表します)。
void compute (int count, float** input, float** output)
この関数をPythonからctypesを介して呼び出し、それを使用してNumPy配列のセットに変換を適用したいと思います。1入力/1出力関数の場合、次のように定義されます。
void compute (int count, float* input, float* output)
次の作品:
import ctypes
import numpy
from numpy.ctypeslib import ndpointer
lib = ctypes.cdll.LoadLibrary('./block.so')
fun = lib.compute
fun.restype = None
fun.argtypes = [ctypes.c_int,
ndpointer(ctypes.c_float),
ndpointer(ctypes.c_float)]
data = numpy.ones(1000).astype(numpy.float32)
output = numpy.zeros(1000).astype(numpy.float32)
fun(1000, data, output)
ただし、複数の入力(および/または出力)に対応するポインター配列を作成する方法がわかりません。何か案は?
編集:人々は、(配列ごとの要素の数に関して)compute
予想される配列ポインターの数をどのように知っているのか疑問に思っています。count
実際、これはハードコーディングされています。与えられたcompute
ものは、期待する入力と出力の数を正確に知っています。それを確認し、適切な数の入力と出力を指すinput
のは、呼び出し元の仕事です。次に、2つの入力を受け取り、1つの出力配列に書き込むoutput
例を示します。compute
virtual void compute (int count, float** input, float** output) {
float* input0 = input[0];
float* input1 = input[1];
float* output0 = output[0];
for (int i=0; i<count; i++) {
float fTemp0 = (float)input1[i];
fRec0[0] = ((0.09090909090909091f * fTemp0) + (0.9090909090909091f * fRec0[1]));
float fTemp1 = (float)input0[i];
fRec1[0] = ((0.09090909090909091f * fTemp1) + (0.9090909090909091f * fRec1[1]));
output0[i] = (float)((fTemp0 * fRec1[0]) - (fTemp1 * fRec0[0]));
// post processing
fRec1[1] = fRec1[0];
fRec0[1] = fRec0[0];
}
}
の署名と実装に影響を与える方法はありませんcompute
。(Pythonから!)必要な入力と出力の数を確認できます。重要な問題は、関数に正しいものを与える方法とargtypes
、NumPy(NumPy配列へのポインターの配列)で適切なデータ構造を生成する方法です。