如何构造ctype结构数组?

时间:2016-04-28 05:45:47

标签: python ctypes

>>> from ctypes import *
>>> class A(Structure):
...  _fields_ = [('a', c_int), ('b', c_int)]
...  def __init__(self, x):
...   self.a = x + 1
...   self.b = x + 2
... 
>>> a = A(1)
>>> a.a
2
>>> a.b
3
>>> b = (A * 2)(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected A instance, got int

我正在尝试在python中构造一个C结构数组,并希望为数组中的每个元素调用构造函数。我怎么能做到这一点?

1 个答案:

答案 0 :(得分:6)

该错误确切地解释了问题,但是有点令人费解:

初始化此类数组的正确方法如下:

structs = [A(1, 2), A(1, 2)]
array = (A * 2)(*structs)

或者,如果您可以在数组构造函数中定义它们,则如下所示:

array = (A * 2)(A(1, 2), A(1, 2))

现在,为什么这样做而你的解决方案没有?因为我将每个参数的{strong>实例 A传递给A * 2的构造函数,这是A的数组。对于传递的每个参数,数组需要A的实例,这正是错误消息。它不希望将参数转换为A,它期望A本身的实例。

分步方法如下:

from ctypes import *
class A(Structure):
    _fields_ = [('a', c_int), ('b', c_int)]

# this create a class which expects 2 A instances
a_array_factory = A * 2
# our first A instance
struct_1 = A(1, 2)
# our second A instance
struct_2 = A(2, 3)
# initialize our array
array = a_array_factory(struct_1, struct_2)

编辑:

由于结构没有本机Python类型,据我所知,没有创建中间结构的解决方案。根据Python documentation,具有C基元的唯一本机类型如下:

ctypes type     C type                                      Python type
c_bool          _Bool                                       bool (1)
c_char          char                                        1-character string
c_wchar         wchar_t                                     1-character unicode string
c_byte          char                                        int/long
c_ubyte         unsigned char                               int/long
c_short         short                                       int/long
c_ushort        unsigned short                              int/long
c_int           int                                         int/long
c_uint          unsigned int                                int/long
c_long          long                                        int/long
c_ulong         unsigned long                               int/long
c_longlong      __int64 or long long                        int/long
c_ulonglong     unsigned __int64 or unsigned long long      int/long
c_float         float                                       float
c_double        double                                      float
c_longdouble    long double                                 float
c_char_p        char * (NUL terminated)                     string or None
c_wchar_p       wchar_t * (NUL terminated)                  unicode or None
c_void_p        void *                                      int/long or Nonee or None