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” - 错误消息的原因。

所以你至少有三种选择:

  1. 难道真的那么重要了“nogil”办呢?如果没有,那就放下它。这是最简单的解决方案,不利的一面:您可能会失去表现。
  2. 使用真正的C阵列,即int *res = (int *) malloc(2*sizeof(int))。它是快速的,不利的一面:你必须自己管理内存。
  3. 使用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。但它也有一个好处,即调用者可以确定结果应该存储在哪种数据结构中(数组或其他类型)。

+0

感谢您列出选项!另一种避开问题的方法是使函数无效,并让它修改一个额外的空白输入数组 – user3433489

+0

@ user3433489简单!没想到这个... – ead