Идея состоит в том, чтобы создать объект 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;
Здесь есть очевидная утечка памяти, так как вы не можете освободить данные, пока arr не будет удален, как указано здесь в красном окне предупреждения. Исправить это, с другой стороны, легко. Определите функцию, которая в основном является функцией-деструктором, которая знает, как выполнять сборку мусора.
void capsule_cleanup(PyObject *capsule) {
void *memory = PyCapsule_GetPointer(capsule, NULL);
// Use your specific gc implementation in place of free if you have to
free(memory);
}
Теперь увеличьте ваш код как,
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);
PyObject *capsule = PyCapsule_New(data, NULL, capsule_cleanup);
// NULL can be a string but use the same string while calling PyCapsule_GetPointer inside capsule_cleanup
PyArray_SetBaseObject((PyArrayObject *) arr, capsule);
return arr;
Нет необходимости в Py_DECREF
капсуле. Функция PyArray_SetBaseObject
ворует справку.
Надеюсь, это поможет!