所以我试图编写一个 C 函数,它接受一个 numpy 数组对象,提取数据,进行一些操作并返回另一个 c 数组作为一个 numpy 数组对象。一切都无缝运行,我使用 python 包装器,这有助于在 python 端轻松操作。但是,我正面临内存泄漏。我有一个 double 输出指针,我对其进行了 malloc 处理,并在将其返回给调用 python 函数之前将其包装到一个 Python 数组对象中,
PyObject *arr;
int nd = 2;
npy_intp dims[] = {5, 10};
double *data = some_function_that_returns_a_double_star(x, y, z);
arr = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, (void *)data);
return arr;
然而,这会造成内存泄漏,因为数据永远不会被释放,我做了一些谷歌搜索,发现这是此类应用程序中的一个问题,解决方案并非易事。我在这方面找到的最有用的资源是 given here .我无法实现此页面从给定示例中讨论的析构函数。有人可以帮我弄这个吗?更具体地说,我正在寻找类似的东西,
PyObject *arr;
int nd = 2;
npy_intp dims[] = {5, 10};
double *data = some_function_that_returns_a_double_star(x, y, z);
arr = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, (void *)data);
some_destructor_that_plug_memLeak_due_to_data_star(args);
return arr;
最佳答案
您不了解的链接中描述的技术是一个很好的技术:创建一个 Python 对象,该对象知道在销毁时如何释放内存,并使其成为返回数组的基础。
听起来您可能对创建新扩展类型的复杂性感到不知所措。幸运的是,这不是必需的。 Python 附带了一种类型,旨在在销毁时执行任意 C 级清理:capsules ,它将一个指针和一个析构函数捆绑在一起,并在胶囊被销毁时调用析构函数。
要为你的内存创建一个胶囊,首先,我们定义一个析构函数:
void capsule_cleanup(PyObject *capsule) {
void *memory = PyCapsule_GetPointer(capsule, NULL);
// I'm going to assume your memory needs to be freed with free().
// If it needs different cleanup, perform whatever that cleanup is
// instead of calling free().
free(memory);
}
然后你将一个胶囊设置为你的阵列的基础
PyObject *capsule = PyCapsule_New(data, NULL, capsule_cleanup);
PyArray_SetBaseObject((PyArrayObject *) arr, capsule);
// Do not Py_DECREF the capsule; PyArray_SetBaseObject stole your
// reference.
这应该确保您的内存在不再使用时被释放。
关于python - PyArray_SimpleNewFromData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52731884/