我有一个C函数uint8_t *begin();
,它返回一个指向已分配内存的指针。
这是ctypes
绑定它:
begin = mylibrary.begin
begin.argtypes = ()
begin.restype = ctypes.POINTER(ctypes.c_uint8)
我需要用整数数组填充内存。有没有更快捷的方法来代替呢?
buffer = begin()
data = range(10)
for idx, value in enumerate(data):
buffer[idx] = ctypes.c_uint8(value)
我不认为迭代整个数组是一种非常快速的方法,因为可迭代数据可以包含很多项,数百万个整数或类似的东西。
答案 0 :(得分:2)
如果您可以添加依赖项,numpy可以让您更轻松。
这是我放在一起的一个例子。
C(注意长度设置为10)
#include <stdlib.h>
int *begin(void) {
return calloc(10, sizeof(int));
}
和python
import numpy as np
import ctypes
# make the data I want to put into C
data = np.arange(10, dtype=ctypes.c_int)
# setup the ctypes just as you did
mylibrary = ctypes.CDLL('a.out')
begin = mylibrary.begin
begin.argtypes = ()
begin.restype = ctypes.POINTER(ctypes.c_int)
# and do the same memmove that Kirill suggested
ctypes.memmove(buffer, data.ctypes.get_data(), ctypes.sizeof(ctypes.c_int)*len(data))
# and print some out
print buffer[2]
# 2
如果你对numpy很聪明,你也可以用这种方式做多维数组。
有人需要考虑一下谁拥有内存以及如何清除它而不是在你接近底层C的任何地方发生段错(或泄漏)。例如del buffer
将不会释放创建的内存缓冲区,必须在C中完成。
答案 1 :(得分:1)
Python列表有对应的C type,我猜有PyObject的内部C数组。因此,您必须迭代列表项,以便将它们转换为int
。可能有一些技巧方法可以在一行中编写它,但我认为越简单越好。
P.S。考虑使用array模块:
>>> import ctypes
>>> from array import array
>>> TenInts = ctypes.c_int * 10
>>> arr = array('i', range(10))
>>> carr = TenInts()
>>> arr_addr, arr_len = arr.buffer_info()[0], len(arr) * arr.itemsize
>>> ctypes.memmove(carr, arr_addr, arr_len)
13893440
>>> print '; '.join(map(str, carr))
0; 1; 2; 3; 4; 5; 6; 7; 8; 9