我想从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)
但是我可以这样做,调用者不必预先分配适当大小的输出数组吗?
答案 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。