Passing a set of NumPy arrays into C function for input and output
To do this specifically with Numpy arrays, you could use:
import numpy as npimport ctypescount = 5size = 1000#create some arraysarrays = [np.arange(size,dtype="float32") for ii in range(count)] #get ctypes handlesctypes_arrays = [np.ctypeslib.as_ctypes(array) for array in arrays]#Pack into pointer arraypointer_ar = (ctypes.POINTER(C.c_float) * count)(*ctypes_arrays)ctypes.CDLL("./libfoo.so").foo(ctypes.c_int(count), pointer_ar, ctypes.c_int(size))
Where the C side of things might look like:
# function to multiply all arrays by 2void foo(int count, float** array, int size){ int ii,jj; for (ii=0;ii<count;ii++){ for (jj=0;jj<size;jj++) array[ii][jj] *= 2; }}
In C, float**
points to first element in a table/array of float*
pointers.
Presumably each of those float*
points to first element in a table/array of float
values.
Your function declaration has 1 count, however it's not clear what this count applies to:
void compute (int count, float** input, float** output)
- 2D matrix
count
xcount
in size? count
-sized array offloat*
each somehow terminated, e.g. withnan
?- null-terminated array of
float*
each ofcount
elements (reasonable assumption)?
Please clarify your question and I will clarify my answer :-)
Assuming the last API interpretation, here's my sample compute function:
/* null-terminated array of float*, each points to count-sized array*/extern void compute(int count, float** in, float** out){ while (*in) { for (int i=0; i<count; i++) { (*out)[i] = (*in)[i]*42; } in++; out++; }}
Test code for the sample compute function:
#include <stdio.h>extern void compute(int count, float** in, float** out);int main(int argc, char** argv){#define COUNT 3 float ina[COUNT] = { 1.5, 0.5, 3.0 }; float inb[COUNT] = { 0.1, -0.2, -10.0 }; float outa[COUNT]; float outb[COUNT]; float* in[] = {ina, inb, (float*)0}; float* out[] = {outa, outb, (float*)0}; compute(COUNT, in, out); for (int row=0; row<2; row++) for (int c=0; c<COUNT; c++) printf("%d %d %f %f\n", row, c, in[row][c], out[row][c]); return 0;}
And how you use same via ctypes in Python for count
== 10 float
subarrays and size 2
float*
array, containing 1 real subarray and NULL terminator:
import ctypesinnertype = ctypes.ARRAY(ctypes.c_float, 10)outertype = ctypes.ARRAY(ctypes.POINTER(ctypes.c_float), 2)in1 = innertype(*range(10))in_ = outertype(in1, None)out1 = innertype(*range(10))out = outertype(out1, None)ctypes.CDLL("./compute.so").compute(10, in_, out)for i in range(10): print in_[0][i], out[0][i]
Numpy interface to ctypes is covered here http://www.scipy.org/Cookbook/Ctypes#head-4ee0c35d45f89ef959a7d77b94c1c973101a562f, arr.ctypes.shape[:] arr.ctypes.strides[:] and arr.ctypes.data are what you need; you might be able to feed that directly to your compute
.
Here's an example:
In [55]: a = numpy.array([[0.0]*10]*2, dtype=numpy.float32)In [56]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0]Out[56]: 0.0In [57]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0] = 1234In [58]: aOut[58]: array([[ 1234., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)