我有一个C++回调函数,使用ctypes调用Python.此函数的参数是指向double数组和元素数的指针.
有很多元素,大约2,000,000.我需要将它发送到scipy函数中.
C++原型是:
bool (*ptsetDataSource)(double*, long long);
Run Code Online (Sandbox Code Playgroud)
这是以下python代码:
CPF_setDataSource = CFUNCTYPE(c_bool, POINTER(c_double),c_longlong)
CPF_setSelection= CFUNCTYPE(c_bool,c_char_p, c_longlong,c_longlong)
CPF_ResetSequence = CFUNCTYPE(c_bool)
def setDataSource(Data, DataLength):
Datalist=[0.0]*100
for i in range(0,100):
Datalist[i]=Data[i]
print Datalist
return True
Run Code Online (Sandbox Code Playgroud)
问题是print datalist返回:
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, …Run Code Online (Sandbox Code Playgroud) 我有一个C函数mallocs()并填充浮点数的二维数组.它"返回"该地址和数组的大小.签名是
int get_array_c(float** addr, int* nrows, int* ncols);
Run Code Online (Sandbox Code Playgroud)
我想用Python调用它,所以我使用ctypes.
import ctypes
mylib = ctypes.cdll.LoadLibrary('mylib.so')
get_array_c = mylib.get_array_c
Run Code Online (Sandbox Code Playgroud)
我从未弄清楚如何使用ctypes指定参数类型.我倾向于为我正在使用的每个C函数编写一个python包装器,并确保我在包装器中获得正确的类型.浮点数组是按主列顺序排列的矩阵,我想把它作为numpy.ndarray.但它非常大,所以我想使用C函数分配的内存,而不是复制它.(我刚刚在StackOverflow中找到了这个PyBuffer_FromMemory的答案:https://stackoverflow.com/a/4355701/3691 )
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)
Run Code Online (Sandbox Code Playgroud)
这似乎给了我一个具有正确值的数组.但我很确定这是一个内存泄漏.
>>> a = get_array_py()
>>> a.flags.owndata
False
Run Code Online (Sandbox Code Playgroud)
该阵列不拥有内存.很公平; 默认情况下,当从缓冲区创建数组时,它不应该.但在这种情况下它应该.删除numpy数组时,我真的很想让python为我释放缓冲区内存.似乎我可以强制将owndata强制为True,那应该这样做,但是owndata是不可设置的.
不满意的解决方案:
让get_array_py()的调用者负责释放内存.这太烦人了; 调用者应该能够像任何其他numpy数组一样处理这个numpy数组.
将原始数组复制到get_array_py中的新numpy数组(具有自己的独立内存),删除第一个数组,并释放get_array_py()中的内存.返回副本而不是原始数组.这很烦人,因为它应该是不必要的内存副本.
有办法做我想要的吗?我不能修改C函数本身,虽然我可以在库中添加另一个C函数,如果这有用的话.
我有无法修改的Swig Python库。
它返回一个<Swig object of type 'double *'>我知道是指向双精度数组的指针的指针。通过一个单独的函数,我得到了一个python int的长度。
我的问题是,如何将这些数据读入numpy?
我找到了numpy.ndarray.ctypes模块,还有另一个stackoverflow答案,提示可能从SWIG转换为ctypes(/sf/answers/2884869711/),但没有提及如何实现。
任何帮助表示赞赏。