pythonctypes

Python: Can we convert a ctypes structure to a dictionary?


I have a ctypes structure.

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

if I have X=S1(), I would like to return a dictionary out of this object: Example, if I do something like: Y = X.getdict() or Y = getdict(X), then Y might look like:

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

Any help ?


Solution

  • Probably something like this:

    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}
    

    As you can see, it works with numbers but it doesn't work as nicely with arrays -- you will have to take care of converting arrays to lists yourself. A more sophisticated version that tries to convert arrays is as follows:

    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
    

    If you have numpy and want to be able to handle multidimensional C arrays, you should add import numpy as np and change:

     value = list(value)
    

    to:

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

    This will give you a nested list.