Similarly to this question, I would like to print the members of a C structure from Python.
I implemented the following function:
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))
The idea is that if the field itself has a _fields_
attribute, then it is a structure, otherwise a normal field so print it. The recursion works fine, but after the first level I'm getting repr
strings printed instead of values. For example:
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
The output I'm expecting would be something like:
foo = 1 bar = 2 baz = 3 innerFoo = 5 innerBar = 23 innerBaz = 56 quz = 4
What is my mistake here?
The solution is pretty simple.
When printing the nested structures, I still need to get the structure as an attribute so ctypes can perform its magic:
print_ctypes_obj(getattr(obj, fname), indent+4)
(another issue with the code is the naming of the iterated pairs; they should be fname, ftype
instead of fname, fvalue
which is incorrect and misleading)
I found this thread very useful, so I add this improved code to support the arrays :
#
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)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With