Max*_*gal 11 c python arrays numpy cython
我正在编写一个Python类,它将包含一个包含C结构的C模块.我使用的是Cython语言(Python和C的超集语言).C结构在构造函数中是malloc,并包含一个我想在Python中使用的数组.该数组将在Python中表示为NumPy数组,但我不想将值复制到它.我想将NumPy数组直接链接到malloc内存.对于此任务,我使用NumPy Array API,特别是此函数:
PyObject*PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
我设法使用Cython中的代码将NumPy数组绑定到C结构的数组,只要NumPy数组和MultimediaParams对象具有相同的生命周期,它就可以正常工作:
cdef class MultimediaParams:
def __init__(self, **kwargs):
self._mm_np = < mm_np *> malloc(sizeof(mm_np))
#some code...
def as_ndarray(self): #TODO: what if self deallocated but numpy array still exists(segfault?)
cdef numpy.npy_intp shape[1]
cdef int arr_size = sizeof(self._mm_np[0].n2) / sizeof(self._mm_np[0].n2[0])
shape[0] = < numpy.npy_intp > arr_size
cdef numpy.ndarray ndarray
ndarray = numpy.PyArray_SimpleNewFromData(1, shape, numpy.NPY_DOUBLE, self._mm_np[0].n2)
return ndarray
def __dealloc__(self):
free(self._mm_np)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该类具有其__dealloc__方法,该方法将处理在C中分配的内存,并在没有对MultimediaParams实例的引用时释放它.
在这种绑定中,NumPy不拥有数组的内存.
问题:当MultimediaParams释放对象并释放数组的内存时,NumPy对象仍然指向刚刚释放的内存.当NumPy对象尝试访问/修改已释放的内存时,这将导致段错误.
MultimediaParams只要有NumPy对象使用其内存,我怎样才能确保对象没有被释放?
据我了解,我需要做的就是让NumPy对象对一个MultimediaParams实例进行引用,从中获取内存指向的实例.我试图使用,ndarray.base = <PyObject*>self所以NumPy会知道它的基础对象,这应该添加对MultimediaParams实例的另一个引用,并且只要NumPy数组处于活动状态就会导致它不被释放.此行导致我的测试失败,因为NumPy数组的内容变为垃圾.
澄清:NumPy数组不占用C数组内存,我不希望它.我想MultimediaParams负责释放C结构(包含数组数据),但只要NumPy对象存活就不要这样做.
有什么建议?
正如 @JFSebastian 的评论指出的那样,问题很可能是,当您正确地将指向实例的指针分配给MultimediaParamsNumPybase数组的引用时,您实际上并没有增加它的引用计数,因为分配是在 C 中进行的,而不是在Python。这可能会导致对象过早进行垃圾回收MultimediaParams,该对象的内存被重用,并导致您在 ndarray 中遇到垃圾数据。
MultimediaParams使用宏手动增加对象的引用计数Py_INCREF应该会产生所需的行为。
| 归档时间: |
|
| 查看次数: |
1385 次 |
| 最近记录: |