2

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

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

4

2 回答 2

2

如果您可以添加依赖项,numpy会使这更容易。

这是我放在一起的一个例子。

C(注意长度设置为10)

#include <stdlib.h>
int *begin(void) {
    return calloc(10, sizeof(int));
}

和蟒蛇

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。

于 2012-05-30T20:08:41.247 回答
1

Python 列表具有相应的C 类型,我猜它具有PyObject的内部 C 数组。因此,您必须遍历列表项才能将它们转换为int's 。可能有一些技巧可以将它写在一行中,但我认为越简单越好。

PS考虑使用数组模块:

>>> 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
于 2012-05-24T05:15:19.960 回答