【问题标题】:Pass a cython allocated buffer to python将 cython 分配的缓冲区传递给 python
【发布时间】:2017-11-10 04:30:42
【问题描述】:

我知道this post 关于将 Cython malloc'ed 数据传递给 Python。但是,我想知道在返回之前转换为 memoryview 是否可以避免内存泄漏:

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 中:

mView = someCythonFunction()

这样安全正确吗?

【问题讨论】:

    标签: python memory-management cython


    【解决方案1】:

    这是不安全且不正确的。它在函数结束时释放内存,这意味着您返回的指针立即无效。

    您需要将内存的生命周期与 Python 对象的生命周期联系起来(在您链接的示例中,内存在析构函数中被释放)。最简单且推荐的方法是使用 numpy 数组或标准库 array 数组(或您选择的其他库)。

    如果您无法避免使用malloc,一种选择是使用cython.view.array class。您可以为它分配一个您选择的回调函数以在销毁时使用,它可以愉快地分配给内存视图:

    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
    

    您可以安全地返回amview(如果您返回a,则无需为mview 烦恼),它们会在正确的时间正确返回。

    【讨论】:

    • 现在你告诉我这很明显。我的印象是它正在工作,因为尽管指针被释放,但数据仍然可以访问并且在 Python 世界中没有损坏。但这可能只是巧合。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 2021-03-03
    • 2016-12-21
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    相关资源
    最近更新 更多