Предположим, что у нас есть C-функция, которая принимает набор из одного или нескольких входных массивов, обрабатывает их и записывает свой вывод в набор выходных массивов. Подпись выглядит следующим образом (с count
, представляющим количество обрабатываемых элементов массива):
void compute (int count, float** input, float** output)
Я хочу вызвать эту функцию из Python через ctypes и использовать ее для применения преобразования к набору массивов NumPy. Для функции с одним входом/одним выходом, определенной как
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
и output
указывают на правильное количество входов и выходов. Здесь пример compute
, содержащий 2 входа и запись в 1 выходной массив:
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).