working with ctypes and complex data structures
Michael Felt
michael at felt.demon.nl
Mon Oct 3 10:35:43 EDT 2016
More information about the Python-list mailing list
Mon Oct 3 10:35:43 EDT 2016
- Previous message (by thread): working with ctypes and complex data structures
- Next message (by thread): working with ctypes and complex data structures
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 02-Oct-16 23:44, eryk sun wrote: > On Sun, Oct 2, 2016 at 5:50 PM, Michael Felt <michael at felt.demon.nl> wrote: >> a) where is documentation on "CField"'s? > It's undocumented. So I do not feel so bad about not finding anything :) > A CField is a data descriptor that accesses a > struct field with the given type, size, and offset. Like most > descriptors, it's meant to be accessed as an attribute of an instance, > not as an attribute of the type. > > When accessed as an attribute of a struct type, the value returned is > the CField descriptor itself. One reason to reference the descriptor > is for its "offset" attribute, since there's no offsetof() in ctypes. > At least in this regard it should be documented. > >> b) what I am not understanding - as the basic documentation shows FOO.value >> as the way to set/get the value of a _field_ > You may be surprised when accessing simple-type fields such as c_int > and c_char_p. These simple types have getter and setter functions that > get called automatically whenever the type is used as a function > result, array index, or struct field. For example: OK - so lucky me - it "does not work" like earlier examples because I am referencing, generally, c_ulonglong - and these do not have a automatic getter/setter function? If not, how do I go about making one (preferably without needing to right a "method" for each and every _field_ in a class. > class Foo(ctypes.Structure): > _fields_ = (('v', ctypes.c_int),) > > >>> foo = Foo() > >>> foo.v = 5 > >>> foo.v > 5 > > You can use a subclass to avoid the getfunc's automatic conversion. For example; > > class my_int(ctypes.c_int): > pass > > class Bar(ctypes.Structure): > _fields_ = (('v', my_int),) > > >>> bar = Bar() > >>> bar.v = 5 > >>> bar.v > <my_int object at 0x7f7385e8aae8> > >>> bar.v.value > 5 I'll try it also with my c_int/c_uint fields - maybe these just work. If so, again - how do I get a c_ulonglong? > >> class time_t(Structure): >> ... >> if (maxsize > 2**32): >> _fields_ = [("v", c_long)] >> else: >> _fields_ = [("v", c_int)] > I'd alias the type instead of defining a struct, e.g. `time_t = > c_long`. This preserves automatic conversion of the simple type. The reason for the not using alias is because a) I was trying to be more inline with the text of the include file. I will have to check the sizeof c_long (i.e., sizeof(long) in both 32 and 64-bit modes > Also, sys.maxsize is based on the platform's size_t type. That's > generally the same size as a pointer, but C doesn't require this. > Instead use sizeof(c_void_p), which will be 8 on a 64-bit platform and > 4 on a 32-bit platform. Thanks! > > Also, while it's unrelated to your current problem, bear in mind that > int and long are both always 32-bit on Windows. c_int64 is a > cross-platform 64-bit integer.
- Previous message (by thread): working with ctypes and complex data structures
- Next message (by thread): working with ctypes and complex data structures
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list