2010-09-24 31 views
10

Tôi có cấu trúc ctypes.Python: Chúng ta có thể chuyển đổi cấu trúc ctypes thành một từ điển không?

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

nếu tôi có X = S1(), tôi muốn quay trở lại một cuốn từ điển ra của đối tượng này: Ví dụ, nếu tôi làm điều gì đó như: Y = X.getdict() hoặc Y = getdict (X) , sau đó Y có thể trông giống như:

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

Bất kỳ trợ giúp nào?

+1

BTW, có lý do nào bạn cần đối tượng 'dict' thực và không thể thêm' __getitem __() 'etc vào các lớp cấu trúc của bạn? – llasram

+0

Trong trường hợp của tôi, tôi muốn một dict của dicts với dữ liệu về quy trình trên một hệ thống ... do đó, nó có ý nghĩa hơn để đặt nó trong một dict của dicts – RobotHumans

Trả lời

10

Có lẽ một cái gì đó như thế này:

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} 

Như bạn thấy, nó hoạt động với những con số nhưng nó không hoạt động như độc đáo với mảng - bạn sẽ phải chăm sóc chuyển đổi mảng vào danh sách cho mình. Một phiên bản phức tạp hơn mà cố gắng để chuyển đổi các mảng như sau:

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 

Nếu bạn có numpy và muốn để có thể xử lý mảng C đa chiều, bạn nên thêm import numpy as np và thay đổi:

value = list(value) 

để :

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

Điều này sẽ cung cấp cho bạn danh sách lồng nhau.

+0

Nice! Gần đó. Tôi vẫn đang đối mặt với một tình huống mới trong đó một cấu trúc ctype S1 có một trường thuộc loại S2 khác. Tự hỏi nếu điều đó có thể được chuyển đổi quá. –

+0

Tôi đã thêm một nhánh khác cố gắng xử lý các cấu trúc lồng nhau (giả thiết rằng các cấu trúc có thể được nhận biết bởi thuộc tính '_fields_' của chúng). Không chắc chắn nếu điều này hoạt động, mặc dù, tôi đã không thử nghiệm nó. –

+0

Sẽ kiểm tra và cho bạn biết. Cảm ơn. –

2

Làm thế nào về một cái gì đó như:

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

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

hơn Một chút mục đích chung để xử lý mảng đôi, và mảng các cấu trúc, và bitfields.

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 
Các vấn đề liên quan