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