Beginner extends C with Python (specifically Numpy)

I am working on a dynamic link with real-time dynamic link, where I have a 2-dimensional C array with floating point data that represents an audio buffer. One dimension is time (sampling), and the other is a channel. I would like to pass this to a python script as a numpy array for DSP processing, and then I would like to pass this back to C so that the data can carry the processing chain to C. The member function in C ++, which processing looks like this:

void myEffect::process (float** inputs, float** outputs, int buffersize) { //Some processing stuff } 

The inputs and outputs of arrays are the same size. Integer buffering is the number of columns in the input and output arrays. On the python side, I would like the processing to be performed by a function that looks like this:

 class myPyEffect ... ... def process(self,inBuff): #inBuff and outBuff should be numpy arrays outBuff = inBuff * self.whatever # some DSP stuff return outBuff ... ... 

Now, my question is: how can I most effectively use data in and out of C (avoiding unnecessary copying of memory, etc.)? So far, for simple parameter changes, I have used C-API calls, such as:

 pValue = PyObject_CallMethod(pInstance, "setParameter", "(f)", value); 

Am I using something similar for my numpy arrays or is there a better way? Thanks for reading.

+6
c ++ c python api numpy
source share
1 answer

You may be able to completely abandon the use of the NumPy C API. Python can call C code using the ctypes module, and you can access pointers to numeric data using the ctypes attribute of the array.

Here is a minimal example showing the process for a 1d sum of square function.

ctsquare.c

 #include <stdlib.h> float mysumsquares(float * array, size_t size) { float total = 0.0f; size_t idx; for (idx = 0; idx < size; ++idx) { total += array[idx]*array[idx]; } return total; } 

compilation in ctsquare.so

These command lines are for OS X, your OS may be different.

 $ gcc -O3 -fPIC -c ctsquare.c -o ctsquare.o $ ld -dylib -o ctsquare.so -lc ctsquare.o 

ctsquare.py

 import numpy import ctypes # pointer to float type, for convenience c_float_p = ctypes.POINTER(ctypes.c_float) # load the library ctsquarelib = ctypes.cdll.LoadLibrary("ctsquare.so") # define the return type and arguments of the function ctsquarelib.mysumsquares.restype = ctypes.c_float ctsquarelib.mysumsquares.argtypes = [c_float_p, ctypes.c_size_t] # python front-end function, takes care of the ctypes interface def myssq(arr): # make sure that the array is contiguous and the right data type arr = numpy.ascontiguousarray(arr, dtype='float32') # grab a pointer to the array data dataptr = arr.ctypes.data_as(c_float_p) # this assumes that the array is 1-dimensional. 2d is more complex. datasize = arr.ctypes.shape[0] # call the C function ret = ctsquarelib.mysumsquares(dataptr, datasize) return ret if __name__ == '__main__': a = numpy.array([1,2,3,4]) print 'sum of squares of [1,2,3,4] =', myssq(a) 
+8
source share

All Articles