I am developing an audio algorithm using Python and Numpy. Now I want to speed up that algorithm by implementing a part of it in C. In the past, I have done this using cython. Now I want to do the same thing using the new cffi.
For testing purposes, I wrote a trivial C function:
void copy(float *in, float *out, int len) { for (int i=0; i<len; i++) { out[i] = in[i]; } }
Now I want to create two numpy arrays and have those be processed by this function. I figured out a way to do that:
import numpy as np from cffi import FFI ffi = FFI() ffi.cdef("void copy(float *in, float *out, int len);") C = ffi.dlopen("/path/to/copy.dll") float_in = ffi.new("float[16]") float_out = ffi.new("float[16]") arr_in = 42*np.ones(16, dtype=np.float32) float_in[0:16] = arr_in[0:16] C.copy(float_in, float_out, 16) arr_out = np.frombuffer(ffi.buffer(float_out, 16*4), dtype=np.float32)
However, I would like to improve this code:
ffi.buffer
is very convenient for quickly converting to contents of a C array to a Numpy array. Is there an equivalent way for quickly converting a numpy array into a C array without copying the individual elements?float_in[0:16] = arr_in[0:16]
is a convenient way of accessing data. The opposite, arr_out[0:16] = float_out[0:16]
does not work however. Why not?You can save your NumPy arrays to CSV files using the savetxt() function. This function takes a filename and array as arguments and saves the array into CSV format. You must also specify the delimiter; this is the character used to separate each variable in the file, most commonly a comma.
Save in npy format using Numpy save() To save this array to . npy file we will use the . save() method from Numpy. Running this line of code will save your array to a binary file with the name 'ask_python.
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 np from cffi import FFI ffi = 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])
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With