我正在研究一个实时音频处理动态链接库,其中我有一个浮点数据的二维C数组,代表音频缓冲区.一个维度是时间(样本),另一个维度是通道.我想把这个传递给一个
python脚本作为DSP处理的numpy数组,然后我想把它传回给C,这样数据就可以继续沿C的处理链传递.C中的成员函数做了处理看起来像这样:
void myEffect::process (float** inputs,float** outputs,int buffersize) { //Some processing stuff }
阵列输入和输出具有相同的大小.整数buffersize是输入和输出数组中的列数.在python方面,我希望处理由一个如下所示的函数执行:
class myPyEffect ... ... def process(self,inBuff): #inBuff and outBuff should be numpy arrays outBuff = inBuff * self.whatever # some DSP stuff return outBuff ... ...
现在,我的问题是,如何以最有效的方式将数据输入和输出C(避免不必要的内存复制等)?到目前为止,对于简单的参数更改,我一直在使用如下的C-API调用:
pValue = PyObject_CallMethod(pInstance,"setParameter","(f)",value);
我是否为我的numpy数组使用类似的东西,还是有更好的方法?谢谢阅读.
解决方法
您可以完全避免处理NumPy C API. Python可以使用ctypes模块调用C代码,并且可以使用数组的ctypes属性访问指向numpy数据的指针.
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; }
汇编到ctsquare.so
这些命令行适用于OS X,您的操作系统可能会有所不同.
$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's 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,4] =',myssq(a)