我正在研究一个实时音频处理动态链接库,其中我有一个浮点数据的二维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数组使用类似的东西,还是有更好的方法?谢谢你的阅读。
答案 0 :(得分:7)
您可以完全避免处理NumPy C API。 Python可以使用ctypes
模块调用C代码,并且可以使用数组的ctypes属性访问指向numpy数据的指针。
这是一个最小的例子,显示了1d平方和函数的过程。
#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;
}
这些命令行适用于OS X,您的操作系统可能会有所不同。
$ gcc -O3 -fPIC -c ctsquare.c -o ctsquare.o
$ ld -dylib -o ctsquare.so -lc ctsquare.o
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,2,3,4] =', myssq(a)