反思嵌套的ctypes结构

时间:2014-11-14 10:19:44

标签: python c introspection

this问题类似,我想从Python打印C结构的成员。

我实现了以下功能:

def print_ctypes_obj(obj, indent=0):
    for fname, fvalue in obj._fields_:
        if hasattr(fvalue, '_fields_'):
            print_ctypes_obj(fvalue, indent+4)
        else:
            print '{}{} = {}'.format(' '*indent, fname, getattr(obj, fname))

这个想法是,如果字段本身具有_fields_属性,那么它是一个结构,否则是一个普通字段,所以打印它。递归工作正常,但在第一级后,我得到repr字符串打印而不是值。例如:

foo = 1
bar = 2
baz = 3
    innerFoo = <Field type=c_long, ofs=0, size=4>
    innerBar = <Field type=c_long, ofs=4, size=4>
    innerBaz = <Field type=c_long, ofs=8, size=4>
quz = 4

我期待的输出类似于:

foo = 1
bar = 2
baz = 3
    innerFoo = 5
    innerBar = 23
    innerBaz = 56
quz = 4

我的错误是什么?

2 个答案:

答案 0 :(得分:4)

解决方案非常简单。

在打印嵌套结构时,我仍然需要将结构作为属性,因此ctypes可以发挥其魔力:

print_ctypes_obj(getattr(obj, fname), indent+4)

(代码的另一个问题是迭代对的命名;它们应该是fname, ftype而不是fname, fvalue,这是不正确和误导的)

答案 1 :(得分:0)

我发现这个线程非常有用,所以我添加了这个改进的代码来支持数组:

#
def print_ctypes_obj(obj, level=0):

    delta_indent="    "
    indent=delta_indent*level

    # Assess wether the object is an array, a structure or an elementary type
    if issubclass(type(obj), ctypes.Array) :
        print('{}ARRAY {}'.format(indent, obj))
        for obj2 in obj:
            print_ctypes_obj(obj2, level+1)

    elif hasattr(obj, '_fields_'):
        print('{}STRUCTURE {}'.format(indent, obj))
        for fdesc in obj._fields_:
            # Get the next field descriptor
            fname = fdesc[0]
            ftype = fdesc[1]
            if len(fdesc)==3:
                fbitlen = fdesc[2]
            else:
                fbitlen = 8*ctypes.sizeof(ftype)
            obj2 = getattr(obj, fname)
            print('{}FIELD {} (type={}, bitlen={})'.format(indent+delta_indent, fname, ftype, fbitlen))
            print_ctypes_obj(obj2, level+2)

    else:
        print('{}VALUE = {} (type={})'.format(indent, obj, type(obj)))