在Python ctypes中使用array.array [英] Using array.array in Python ctypes

查看:304
本文介绍了在Python ctypes中使用array.array的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须将Python程序与C库接口。我需要调用的特定函数需要一个数组并返回一个double。以下函数具有相同的签名,比我自己的函数更易于理解:

I have to interface a Python program with a C library. The particular function I need to call takes an array and returns a double. The following function has the same signature and is easier to understand than my own:

double sum(double * array, const int length) {
 double total = 0;
 int i;
 for (i=0; i<length; i++) {
     total += array[i];
 }
 return total;
}

我当前的解决方案是:

import ctypes
lib = ctypes.CDLL(library_name) 

l = 10
arr = tuple(range(l))

lib.sum.restype = ctypes.c_double
values = (ctypes.c_double * l)(*arr)
ret = lib.sum(values, l)

但是我在代码中经常使用数组模块,在我看来,将它们与C代码一起使用应该是更直截了当的类型,因为它是类型数组。因此,我尝试将C函数直接提供给数组,但没有用。为了使其工作,我像这样包装了数组:

But I use the array module a lot in my code and it seemed to me that using them with the C code should be more straight forward as it is a typed array. So I tried to feed the C function directly with an array but it did not work. To make it work, I wrapped array like this:

class Array(array):

   @property
   def _as_parameter_(self):
      return (TYPES[self.typecode] * len(self))(*self)

其中TYPES将数组中的类型代码映射到ctypes类型:

where TYPES map the typecode from the array to ctypes types:

   TYPES = {'c': ctypes.c_char,
            'b': ctypes.c_byte,
            'B': ctypes.c_ubyte,
            '?': ctypes.c_bool,
            'h': ctypes.c_short,
            'H': ctypes.c_ushort,
            'i': ctypes.c_int,
            'I': ctypes.c_uint,
            'l': ctypes.c_long,
            'L': ctypes.c_ulong,
            'q': ctypes.c_longlong,
            'Q': ctypes.c_ulonglong,
            'f': ctypes.c_float,
            'd': ctypes.c_double}

是否有替换方法_as_parameter_不会创建另一个数组?

Is there a way to replace _as_parameter_ by something that does not create another array?

谢谢

推荐答案

使用array.buffer_info()获取地址和长度,并将地址强制转换为POINTER( c_double):

use array.buffer_info() to get the address and length, and cast() the address to POINTER(c_double):

from array import array
buf = array("d", range(101))
addr, count = buf.buffer_info()
print lib.sum(cast(addr, POINTER(c_double)), count)

这篇关于在Python ctypes中使用array.array的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆