Python CFFI convert structure to dictionary

python, python-cffi

Solution

Arpegius' solution works fine for me, and is quite elegant. I implemented a solution based on Selso's suggestion to use inspect. dir() can substitute inspect.

from inspect import getmembers
from cffi import FFI
ffi = FFI()
from pprint import pprint

def cdata_dict(cd):
    if isinstance(cd, ffi.CData):
        try:
            return ffi.string(cd)
        except TypeError:
            try:
                return [cdata_dict(x) for x in cd]
            except TypeError:
                return {k: cdata_dict(v) for k, v in getmembers(cd)}
    else:
        return cd

foo = ffi.new("""
struct Foo {
    char name[6];
    struct {
        int a, b[3];
    } item;
} *""",{
    'name': b"Foo",
    'item': {'a': 3, 'b': [1, 2, 3]}
})
pprint(cdata_dict(foo))

Output:

{'item': {'a': 3, 'b': [1, 2, 3]}, 'name': b'Foo'}

Problem

There is a way to initialize structure with dictionary: ``` fooData= {'y': 1, 'x': 2} fooStruct = ffi.new("foo_t*", fooData) fooBuffer = ffi.buffer(fooStruct) ``` Is there some ready function to do the conversion? ``` fooStruct = ffi.new("foo_t*") (ffi.buffer(fooStruct))[:] = fooBuffer fooData= convert_to_python( fooStruct[0] ) ``` Do I have to use ffi.typeof("foo_t").fields by myself? I come up with this code so far: ``` def __convert_struct_field( s, fields ): for field,fieldtype in fields: if fieldtype.type.kind == 'primitive': yield (field,getattr( s, field )) else: yield (field, convert_to_python( getattr( s, field ) )) def convert_to_python(s): type=ffi.typeof(s) if type.kind == 'struct': return dict(__convert_struct_field( s, type.fields ) ) elif type.kind == 'array': if type.item.kind == 'primitive': return [ s[i] for i in range(type.length) ] else: return [ convert_to_python(s[i]) for i in range(type.length) ] elif type.kind == 'primitive': return int(s) ``` Is there a faster way?

Original source