How to pass a Numpy array into a cffi function and how to get one back out? How to pass a Numpy array into a cffi function and how to get one back out? python python

How to pass a Numpy array into a cffi function and how to get one back out?


The ctypes attribute of ndarray can interact with the ctypes module, for example, ndarray.ctypes.data is the data address of the array, you can cast it to a float * pointer,and then pass the pointer to the C function.

import numpy as npfrom cffi import FFIffi = FFI()ffi.cdef("void copy(float *in, float *out, int len);")C = ffi.dlopen("ccode.dll")a = 42*np.ones(16, dtype=np.float32)b = np.zeros_like(a)pa = ffi.cast("float *", a.ctypes.data)pb = ffi.cast("float *", b.ctypes.data)C.copy(pa, pb, len(a))print b

For your question 3:

I think ffi array doesn't provide numpy the necessary information to access it's inner buffer. So numpy try to convert it to a float number which failed.

The best solution I can thinks is convert it to list first:

float_in[0:16] = list(arr_in[0:16])


the data in a numpy array can be accessed via it's array interface:

import numpy as npimport cffiffi = cffi.FFI()a = np.zeros(42)data = a.__array_interface__['data'][0]cptr = ffi.cast ( "double*" , data )

now you have a cffi pointer type, which you can pass to your copy routine. note that this is a basic approach; numpy arrays may not contain their data in flat memory, so if your ndarray is structured, you will have to consider it's shape and strides. If it's all flat, though, this is sufficient.


An update to this: modern versions of CFFI have ffi.from_buffer(), which turns any buffer object (like a numpy array) to a char * FFI pointer. You can now do directly:

cptr = ffi.cast("float *", ffi.from_buffer(my_np_array))

or directly as arguments to the call (the char * is casted automatically to float *):

C.copy(ffi.from_buffer(arr_in), ffi.from_buffer(arr_out), 16)