2010-09-24 132 views
10

我有一個ctypes結構。Python:我們可以將ctypes結構轉換爲字典嗎?

class S1 (ctypes.Structure): 
    _fields_ = [ 
    ('A',  ctypes.c_uint16 * 10), 
    ('B',  ctypes.c_uint32), 
    ('C',  ctypes.c_uint32) ] 

,如果我有X = S1(),我想回字典出這個對象的:例如,如果我這樣做:Y = X.getdict()或Y = getdict(X) ,那麼Y可能看起來像:

{ 'A': [1,2,3,4,5,6,7,8,9,0], 
    'B': 56, 
    'C': 8986 } 

任何幫助嗎?

+1

順便說一句,是否有一個原因,你需要一個真正的'dict'對象,不能只是添加'__getitem __()'等方法到你的結構類? – llasram 2010-09-24 18:31:20

+0

在我的情況下,我想要一個有關係統進程數據的字典詞典...所以它更有意義,把它放在一個字典的字典 – RobotHumans 2012-03-01 12:22:29

回答

10

大概是這樣的:

def getdict(struct): 
    return dict((field, getattr(struct, field)) for field, _ in struct._fields_) 

>>> x = S1() 
>>> getdict(x) 
{'A': <__main__.c_ushort_Array_10 object at 0x100490680>, 'C': 0L, 'B': 0L} 

正如你所看到的,它的工作原理與數字,但它不會與數組作爲工作得很好 - 你將不得不採取自己的陣列轉換成列表的照顧。試圖轉換陣列更復雜的版本如下:

def getdict(struct): 
    result = {} 
    for field, _ in struct._fields_: 
     value = getattr(struct, field) 
     # if the type is not a primitive and it evaluates to False ... 
     if (type(value) not in [int, long, float, bool]) and not bool(value): 
      # it's a null pointer 
      value = None 
     elif hasattr(value, "_length_") and hasattr(value, "_type_"): 
      # Probably an array 
      value = list(value) 
     elif hasattr(value, "_fields_"): 
      # Probably another struct 
      value = getdict(value) 
     result[field] = value 
    return result 

如果你有numpy,並希望能夠處理多維C數組,你應該添加import numpy as np和變化:

value = list(value) 

到:

value = np.ctypeslib.as_array(value).tolist() 

這會給你一個嵌套列表。

+0

好!就快到了。我仍然面臨一種新的情況,其中一個ctype結構S1具有另一種類型的字段S2。不知道是否可以轉換。 – 2010-09-24 18:08:07

+0

我已經添加了另一個試圖處理嵌套結構的分支(假設結構可以被他們的'_fields_'屬性識別)。不知道這是否有效,但我沒有測試過。 – 2010-09-24 18:29:28

+0

將測試並讓你知道。謝謝。 – 2010-09-30 03:24:07

2

如何像:

class S1(ctypes.Structure): 
    _fields_ = [ ... ] 

    def getdict(self): 
     dict((f, getattr(self, f)) for f, _ in self._fields_) 
1

多一點點的通用處理雙陣列和結構的陣列,以及位域。

def getdict(struct): 
    result = {} 
    #print struct 
    def get_value(value): 
     if (type(value) not in [int, long, float, bool]) and not bool(value): 
      # it's a null pointer 
      value = None 
     elif hasattr(value, "_length_") and hasattr(value, "_type_"): 
      # Probably an array 
      #print value 
      value = get_array(value) 
     elif hasattr(value, "_fields_"): 
      # Probably another struct 
      value = getdict(value) 
     return value 
    def get_array(array): 
     ar = [] 
     for value in array: 
      value = get_value(value) 
      ar.append(value) 
     return ar 
    for f in struct._fields_: 
     field = f[0] 
     value = getattr(struct, field) 
     # if the type is not a primitive and it evaluates to False ... 
     value = get_value(value) 
     result[field] = value 
    return result