Posso forçar um ndarray numpy a se apropriar de sua memória?

Tenho uma função C que mallocs () e preenche uma matriz 2D de carros alegóricos. Ele "retorna" esse endereço e o tamanho da matriz. A assinatura é

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

Eu quero chamá-lo de Python, então eu uso ctypes.

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

Eu nunca descobri como especificar tipos de argumento com ctypes. Costumo escrever apenas um wrapper python para cada função C que estou usando e garantir que os tipos estejam corretos no wrapper. A matriz de carros alegóricos é uma matriz na ordem das colunas principais, e eu gostaria de obtê-lo como um numpy.ndarray. Mas é bem grande, então eu quero usar a memória alocada pela função C, não copiá-la. (Acabei de encontrar esse material PyBuffer_FromMemory nesta resposta 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)

Isto parece me dar uma matriz com os valores certos. Mas tenho certeza de que é um vazamento de memória.

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

A matriz não possui a memória. Justo; por padrão, quando a matriz é criada a partir de um buffer, não deveria. Mas neste caso deveria. Quando a matriz numpy é excluída, eu realmente gostaria que o python liberasse a memória do buffer para mim. Parece que se eu pudesse forçar owndata para True, isso deveria ser feito, mas owndata não é configuráve

Soluções insatisfatórias:

Torne o chamador de get_array_py () responsável por liberar a memória. Isso é super chato; o chamador deve poder tratar essa matriz numpy como qualquer outra matriz nump

Copie a matriz original para uma nova matriz numpy, ay (com memória própria e separada) em get_array_py, exclua a primeira matriz e libere a memória dentro de get_array_py (). Retorne a cópia em vez da matriz original. Isso é irritante porque é uma cópia de memória desnecessári

Existe uma maneira de fazer o que eu quero? Não consigo modificar a função C, apesar de poder adicionar outra função C à biblioteca, se isso for úti

questionAnswers(2)

yourAnswerToTheQuestion