嵌入一​​个 python/cython numpy 数组:将 numpy 数组传递给 c 指针

Embedding a python/cython numpy array: Passing numpy array to c pointer

我正在尝试将 cython-numpy 数组传递给 c 结构。这有时会起作用,但如果数组变得太 'large' 就会崩溃。虽然这并不是很大(比如 <100k 双类型条目),但我不知道这个限制是从哪里来的。一些代码片段(附上完整代码)。

基于 Win7、Cython 0.28.4、Python3.6、mingw64

我用不同长度的数组试过了。我最近发现,如果数组长度大于 2**16-512 个条目,它总是会崩溃。但我不知道为什么。

cython 文件:

//cy_file.pyx
//...
cdef public struct Container:
    double* np_array
// ...
cdef public void create_np_array(Container *container):
  cdef numpy.ndarray[numpy.float_t, ndim=1, mode = 'c'] np_array
  # just create a numpy array 
  longarray = np.linspace(1.0, 5.0, 100000)
  np_array = numpy.ascontiguousarray(numpy.array(longarray), dtype=float)
  container.np_array = <double*> np_array.data

对于 c 文件:

//c_file.c
#include "Python.h"
#include "cy_file.h"

struct Container container;
//...
Py_Initialize();
PyInit_cy_file();
// and call the cython function that fills up the numpy array
create_np_array(&container, start, stop, n_elements, n);
// shutdown of python interpreter
Py_Finalize();

// *** here comes the crash if the array longarray is 'too long' ***
container.np_array[0]

谁能告诉我这里出了什么问题或如何调试?

感谢和欢呼, 蒂姆

内存归 Numpy 数组所有,当 numpy 数组的引用计数降为零时被释放,这很可能是在 create_np_array 结束时。 Py_Finalize() 尝试释放 所有 剩余的 Python 个对象失败。

您访问此内存的尝试总是无效 - 它仅对特定大小的数组失败的事实只是"luck"。

没有任何一种好的解决方案,但这里有一些建议:

  1. 使用Py_INCREF手动增加拥有的numpy数组的引用计数(然后当你用完它持有的内存时再次手动减少它)这样它就不会被破坏在函数的末尾。确保在 Py_Finalize.

  2. 之前保持内存访问
  3. 处理 C 代码中的内存分配并将其分配给 Numpy 数组,以便使用 PyArray_SimpleNewFromData 使 numpy 数组不拥有它。您必须注意 Numpy 数组的寿命不会超过内存。

好的,终于找到了有用提示的答案:

这个想法在 blog post 中得到了最好的描述,包括 github 上的完整代码示例。所以我只是参考这个 post 在这里,它非常详细地回答了这个问题。

谢谢!