将cython分配的缓冲区传递给python [英] Pass a cython allocated buffer to python
问题描述
我知道这篇文章关于将Cython malloc的数据传递给Python.但是我想知道是否在返回之前强制转换为memoryview可以避免内存泄漏:
I am aware of this post about passing over Cython malloc'ed data to Python. I however wonder if casting to a memoryview before returning avoids the memory leak:
def someCythonFunction():
try:
mPtr = <double *>PyMem_Malloc(N * M * sizeof(double)
for n in range(N):
for m in range(M):
mPtr[m + n*M]= ...
return <double[:N,:M]> mPtr
finally:
print("In cython %d" % <int>mPtr)
PyMem_Free(mPtr)
然后在Python中:
then in Python:
mView = someCythonFunction()
这是安全正确的吗?
推荐答案
这是不安全且不正确的.当函数结束时,它将释放内存,这意味着您返回的指针立即无效.
This is unsafe and incorrect. It deallocates the memory as the function ends which means the pointer that you return is immediately invalid.
您需要将内存的生存期与Python对象的生存期联系起来(如您所链接的示例中,在析构函数中释放了内存).推荐的最简单方法是使用numpy数组或标准库array
数组(或您选择的其他库).
You need to tie the lifetime of the memory to the lifetime of a Python object (as in the example you linked to, the memory is freed in the destructor). The simplest and recommended way of doing this is to use a numpy array or a standard library array
array (or other library of your choice).
如果您无法避免使用malloc
,一种选择是使用 cython.view.array
类.您可以为其选择分配一个回调函数以用于销毁,并且可以愉快地将其分配给memoryviews:
If you can't avoid using malloc
one option is to use the cython.view.array
class. You can assign it a callback function of your choice to use on destruction and it can be happily assigned to memoryviews:
cdef double[:,:] mview
cdef double* mPtr = <double *>PyMem_Malloc(N * M * sizeof(double))
a = cython.view.array(shape=(N, M), itemsize=sizeof(double), format="d",
mode="C", allocate_buffer=False)
a.data = <char *> mPtr
a.callback_free_data = PyMem_Free
mview = a
您可以安全地返回a
或mview
(如果您返回a
则无需费心mview
),它们将在正确的时间正确获得.
You can safely return either a
or mview
(if you return a
then there's no need to bother with mview
) and they will get correctly at the right time.
这篇关于将cython分配的缓冲区传递给python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!