填充python ctypes指针

时间:2012-05-24 03:41:28

标签: python ctypes

我有一个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)

我不认为迭代整个数组是一种非常快速的方法,因为可迭代数据可以包含很多项,数百万个整数或类似的东西。

2 个答案:

答案 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