Puedo obligar a un ndarray numpy a tomar posesión de su memori

Tengo una función C que mallocs () y llena una matriz 2D de flotantes. "Devuelve" esa dirección y el tamaño de la matriz. La firma es

int get_array_c(float** addr, int* nrows, int* ncols);

Quiero llamarlo desde Python, así que uso ctypes.

import ctypes
mylib = ctypes.cdll.LoadLibrary('mylib.so')
get_array_c = mylib.get_array_c

Nunca descubrí cómo especificar tipos de argumentos con ctypes. Tiendo a escribir un contenedor de Python para cada función C que estoy usando, y me aseguro de obtener los tipos correctos en el contenedor. La matriz de flotantes es una matriz en el orden de columnas principales, y me gustaría obtenerla como numpy.ndarray. Pero es bastante grande, así que quiero usar la memoria asignada por la función C, no copiarla. (Acabo de encontrar estas cosas de PyBuffer_FromMemory en esta respuesta de StackOverflow:https: //stackoverflow.com/a/4355701/369)

buffer_from_memory = ctypes.pythonapi.PyBuffer_FromMemory
buffer_from_memory.restype = ctypes.py_object

import numpy
def get_array_py():
    nrows = ctypes.c_int()
    ncols = ctypes.c_int()
    addr_ptr = ctypes.POINTER(ctypes.c_float)()
    get_array_c(ctypes.byref(addr_ptr), ctypes.byref(nrows), ctypes.byref(ncols))
    buf = buffer_from_memory(addr_ptr, 4 * nrows * ncols)
    return numpy.ndarray((nrows, ncols), dtype=numpy.float32, order='F',
                         buffer=buf)

Esto parece darme una matriz con los valores correctos. Pero estoy bastante seguro de que es una pérdida de memoria.

>>> a = get_array_py()
>>> a.flags.owndata
False

La matriz no posee la memoria. Lo suficientemente justo; de forma predeterminada, cuando la matriz se crea desde un búfer, no debería. Pero en este caso debería. Cuando se elimina la matriz numpy, realmente me gustaría que Python libere la memoria del búfer para mí. Parece que si pudiera forzar owndata a True, eso debería hacerlo, pero owndata no es configurable.

Soluciones insatisfactorias:

Haga que la persona que llama de get_array_py () se encargue de liberar la memoria. Eso es súper molesto; la persona que llama debería poder tratar esta matriz numpy como cualquier otra matriz numpy.

Copie la matriz original en una nueva matriz numpy, ay (con su propia memoria separada) en get_array_py, elimine la primera matriz y libere la memoria dentro de get_array_py (). Devuelve la copia en lugar de la matriz original. Esto es molesto porque es una copia de memoria innecesari

¿Hay alguna forma de hacer lo que quiero? No puedo modificar la función C en sí, aunque podría agregar otra función C a la biblioteca si eso es útil.

Respuestas a la pregunta(4)

Su respuesta a la pregunta