2011-05-19 41 views
3

我有一个具有不同数据类型字段的结构。我想遍历结构字段,检查数据类型,并设置适当的值的字段。如何从ctypes结构或联合字段获得'type'字段描述符

我可以通过字段的.size和.offset属性访问字段的大小和偏移量。我如何获得该字段的'type'属性?使用类型(值)不会打印特定字段的ctypes数据类型。如果我打印值然后我看到ctypes数据类型,但似乎没有一个属性直接访问此。

如何直接访问类型字段描述符?

from ctypes import * 

class A(Structure): 
    _fields_ = [("one", c_long), 
       ("two", c_char), 
       ("three", c_byte)] 

>>> A.one 
<Field type=c_long, ofs=0, size=4> 
>>> A.one.offset 
0 
>>> A.one.size 
4 
>>> type(A.one) 
<class '_ctypes.CField'> 

我非常希望得到类似下面的代码片段字段类型...

>>> A.one.type 
c_long 

回答

4

只需使用_fields_列表:

>>> for f,t in A._fields_: 
... a = getattr(A,f) 
... print a,a.offset,a.size,t 
... 
<Field type=c_long, ofs=0, size=4> 0 4 <class 'ctypes.c_long'> 
<Field type=c_char, ofs=4, size=1> 4 1 <class 'ctypes.c_char'> 
<Field type=c_byte, ofs=5, size=1> 5 1 <class 'ctypes.c_byte'> 
3

这似乎并不在ctypes的API支持。当创建Field再版<Field type=c_long ..>,该名称是从嵌入式检索这样的:

name = ((PyTypeObject *)self->proto)->tp_name; 

对于你的领域的成员self->protoc_long,但是我发现在Python 2.7的cfield.c在那里你可以没有地方检索self->proto本身的值。您可能会被迫:

  1. 创建您自己的映射从nametype
  2. (yuck)解析repr为<Field type=X并使用getattr(ctypes, X)来获取类型对象。

只是为了与选项(1)为例跟进,这里是一类装饰它为您创建类型映射,加入_typeof(cls, fld)类方法:

from ctypes import * 

def typemap(cls): 
    _types = dict((getattr(cls, t), v) for t, v in cls._fields_) 
    setattr(cls, '_typeof', classmethod(lambda c, f: _types.get(f))) 
    return cls 

@typemap 
class A(Structure): 
    _fields_ = [("one", c_long), 
       ("two", c_char), 
       ("three", c_byte)] 

print A._typeof(A.one), A._typeof(A.two), A._typeof(A.three) 

结果:

<class 'ctypes.c_long'> <class 'ctypes.c_char'> <class 'ctypes.c_byte'>