ctypes and flexible (zero-length) arrays
Dear lazyweb, I’ve been racking my brain trying to get information out of the following C struct in a nice way when using ctypes:
struct Foo { unsigned int length; char name[]; }; |
I wrote a little C function to get instance of the struct easily into python:
struct Foo * put_name(char *name) { struct Foo *foo = malloc(sizeof(struct Foo) + strlen(name)); foo->length = strlen(name); memcpy(foo->name, name, foo->length); return(foo); } |
Now, how do I actually get the full contents of Foo.name in python? The only way I could think of that actually works is to create a dummy-struct type in order to get the length out and then use it to dynamically create a new sub-class of ctypes.Structure, then create an instance based on the address of what was returned. I think the following shows it pretty clearly:
class FOO(Structure): _fields_ = [('length', c_uint), ('name', c_char * 0)] liblib = cdll.LoadLibrary('./_build/liblib.so') c_put_name = liblib.put_name c_put_name.argtypes = [c_char_p] c_put_name.restype = POINTER(FOO) def put_name(str): f = c_put_name(str) K = type('FOO%s' % f.contents.length, (Structure,), {'_fields_' : [('length', c_uint), ('name', c_char * f.contents.length)]}) return K.from_address(addressof(f.contents)) |
I still think there ought to be some other way that ‘feels’ nicer. I mean the use of “short arrays” (declared as here with [], or zero size as supported by GCC, or the more portable array of size one) seems to be common enough to warrant some support from ctypes, right?
Any suggestions for improvements?