2011-05-19 44 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'>