2010-09-24 58 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