Cython:创建返回数组的C函数
问题描述:
我想创建一个读取数组并返回数组的Cython函数。这个函数可以在其他cdef函数中调用,而不是python def函数。这是我的。Cython:创建返回数组的C函数
在我.pxd文件:
cdef int[:] array_test(double *x) nogil
在我.pyx文件:
cdef inline int[:] array_test(double *x) nogil:
cdef int output[2]
output[0]=1
output[1]=9
return output
但是,当我编译,我得到的错误: “不允许操作不吉” 可有人请帮忙?
答
可能存在一个误解:该函数不会返回一个c数组,而是一个内存视图片。您不必相信我,您可以通过删除nogil
并调用cython来检查它。在创建的* .c文件,你可以看到你的函数的C-签名,__Pyx_memviewslice
作为重要的组成部分:
static CYTHON_INLINE __Pyx_memviewslice __pyx_f_4file_array_test(CYTHON_UNUSED double *__pyx_v_x)
此内存视图是一个Python对象,因此它必须在垃圾收集器进行注册和因此需要全局解释器锁 - 这就是您看到“操作不允许没有gil” - 错误消息的原因。
所以你至少有三种选择:
- 难道真的那么重要了“nogil”办呢?如果没有,那就放下它。这是最简单的解决方案,不利的一面:您可能会失去表现。
- 使用真正的C阵列,即
int *res = (int *) malloc(2*sizeof(int))
。它是快速的,不利的一面:你必须自己管理内存。 - 使用c + +和
std::vector<int>
,好处是,你不必再管理内存,但你需要切换到C++。
的可能性1.改进是将收购吉只在最后一行,在需要的地方(这不会使这个例子,但可能真正的代码更差):
cdef inline int[:] array_test(double *x) nogil:
cdef int output[2]
output[0]=1
output[1]=9
with gil:
return output
如OP提出,另一可能性是该函数的签名更改为:
cdef inline void array_test(double *x, int[:] output) nogil:
这里的技巧:功能array_test
不再创建结果内存视图切片,并且不必在垃圾回收器中注册它,因此“nogil”是可能的。
有一些轻微的缺点,如呼叫array_test
变得更加繁琐,并且调用者必须具有gil才能创建内存视图output
。但它也有一个好处,即调用者可以确定结果应该存储在哪种数据结构中(数组或其他类型)。
感谢您列出选项!另一种避开问题的方法是使函数无效,并让它修改一个额外的空白输入数组 – user3433489
@ user3433489简单!没想到这个... – ead