在Cython和NumPy中包装C函数

时间:2012-04-08 03:33:46

标签: python c numpy cython wrapping

我想从Python调用我的C函数,以便操作一些NumPy数组。功能是这样的:

void c_func(int *in_array, int n, int *out_array);

结果在out_array中提供,其大小我事先知道(实际上不是我的函数)。我尝试在相应的.pyx文件中执行以下操作,以便能够将输入从NumPy数组传递给函数,并将结果存储在NumPy数组中:

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array):    
    n = len(in_array)
    out_array = np.zeros((512,), dtype = np.int32)
    mymodule.c_func(<int *> in_array.data, n, <int *> out_array.data)
    return out_array

但我明白了 输出分配的"Python objects cannot be cast to pointers of primitive types"错误。我该如何做到这一点?

(如果我要求Python调用者分配正确的输出数组,那么我可以

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array, np.ndarray[np.int32_t, ndim=1] out_array):  
    n = len(in_array)
    mymodule.cfunc(<int *> in_array.data, n, <int*> out_array.data)

但是我可以这样做,调用者不必预先分配适当大小的输出数组吗?

2 个答案:

答案 0 :(得分:5)

您应该在cdef np.ndarray分配之前添加out_array

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array):    
    cdef np.ndarray out_array = np.zeros((512,), dtype = np.int32)
    n = len(in_array)
    mymodule.c_func(<int *> in_array.data, n, <int *> out_array.data)
    return out_array

答案 1 :(得分:1)

这是一个如何使用C / C ++通过ctypes编写的代码来操作NumPy数组的示例。 我在C中编写了一个小函数,从第一个数组中取出数字的平方并将结果写入第二个数组。元素的数量由第三个参数给出。此代码编译为共享对象。

square.c编译为squares.so:

void square(double* pin, double* pout, int n) {
    for (int i=0; i<n; ++i) {
        pout[i] = pin[i] * pin[i];
    }
}

在python中,您只需使用ctypes加载库并调用该函数。数组指针从NumPy ctypes接口获得。

import numpy as np
import ctypes

n = 5
a = np.arange(n, dtype=np.double)
b = np.zeros(n, dtype=np.double)

square = ctypes.cdll.LoadLibrary("./square.so")

aptr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
bptr = b.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
square.square(aptr, bptr, n)

print b

这适用于任何c库,你只需知道要传递哪些参数类型,可能使用ctypes在python中重建c-structs。