代码之家  ›  专栏  ›  技术社区  ›  learnvst

初学者用python扩展c(特别是numpy)

  •  6
  • learnvst  · 技术社区  · 16 年前

    我正在研究一个实时音频处理动态链接库,其中有一个表示音频缓冲区的浮点数据的二维c数组。一个维度是时间(样本),另一个是通道。我想把它传递给一个Python脚本,作为DSP处理的一个麻木数组,然后我想把它传递回C,这样数据就可以在C中进行处理链。

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

    数组 输入 输出 大小相等。整数 缓冲区大小 是中的列数 输入 输出 数组。在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数组使用类似的方法吗?还是有更好的方法?谢谢你的阅读。

    1 回复  |  直到 16 年前
        1
  •  7
  •   Theran    16 年前

    您可能能够完全避免处理numpy c api。python可以使用 ctypes 模块,您可以使用数组的ctypes属性访问指向numpy数据的指针。

    这里有一个最小的例子,展示了一维平方和函数的过程。

    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

    这些命令行是针对OSX的,您的操作系统可能会有所不同。

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

    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,2,3,4] =', myssq(a)