用Cython扩展numpy
我正在尝试把一个包含很多函数的头文件包装起来,像这样:
test.h
void test(int N, int* data_in, int* data_out);
这样我就可以在numpy中使用这些函数。
现在我有以下的cython代码:
test.pyx
import numpy as np
cimport numpy as np
ctypedef np.int_t itype_t
cdef extern from 'VolumeForm.h':
void _test 'test' (int, int*, int*)
def wrap_test(np.ndarray[itype_t, ndim=2] data):
cdef np.ndarray[dtype_t, ndim=1] out
out = np.zeros((data.shape[0],1), dtype=np.double)
_test(
data.shape[0],
<itype_t*> data.data,
<itype_t*> out.data
)
return out
但是,当我尝试编译它时,我遇到了这个错误:
Error converting Pyrex file to C:
(...)
Cannot assign type 'test.itype_t *' to 'int *'
我该如何解决这个问题呢?
2 个回答
2
还有一种解决办法,不需要你把 int
改成 long
。你只需要在 cdef extern from '...'
这个块里修改函数的定义。Cython 在生成 .c
文件的时候,只是用 cdef extern
块里的声明来检查类型,但生成的 C 代码只是简单地做了一个 #include "VolumeForm.h"
,所以你可以这样做而不会出问题。
import numpy as np
cimport numpy as np
ctypedef np.int_t itype_t
cdef extern from 'VolumeForm.h':
# NOTE: We changed the int* declarations to itype_t*
void _test 'test' (int, itype_t*, itype_t*)
def wrap_test(np.ndarray[itype_t, ndim=2] data):
cdef np.ndarray[dtype_t, ndim=1] out
out = np.zeros((data.shape[0],1), dtype=np.double)
_test(
data.shape[0],
<itype_t*> data.data,
<itype_t*> out.data
)
return out
Cython 对上述内容不会报错。
4
这个问题目前正在Cython的邮件列表上讨论;看起来是因为Cython库中的一个小错误引起的:
http://codespeak.net/mailman/listinfo/cython-dev
现在,有一个可能的解决办法是使用NumPy数组,类型设置为np.long,然后把'ctypedef np.long_t itype_t'写成这样。接下来,你只需要让C代码使用长整型(long ints)而不是整型(ints)就可以了。