ctypes and byte order

Peter Otten __peter__ at web.de
Thu Jun 18 08:24:03 EDT 2015


Jean-Michel Pichavant wrote:

> ----- Original Message -----
>> From: "Peter Otten" <__peter__ at web.de>
>> becomes
>> 
>> $ cat be2.py
>> import ctypes, sys
>> 
>> iarray_be = ctypes.c_uint32.__ctype_be__*5
>> 
>> class Foo_be(ctypes.BigEndianStructure):
>>         _fields_ = [('bar', iarray_be)]
>> 
>> print sys.version
>> f_be = Foo_be((0,1,2,3,0x11223344))
>> print hex(f_be.bar[4])
>> 
>> $ python be2.py
>> 2.7.6 (default, Mar 22 2014, 22:59:56)
>> [GCC 4.8.2]
>> 0x11223344L
>> 
>> which might do what you want.
> 
> Brilliant !
> 
> I've tested it and it yields the exact same results (binary file content
> wise) than my "workaround" structure. But that's way better since my
> actual structure is more complex and arrays will be required.
> 
> Though I'm slightly puzzled by the ctypes author(s) choice, this is not
> documented and requires to peek into the source code. Dunder attributes
> are rarely part of an interface.

On further reflection it dawned on me that what may have made this work is 
passing in the tuple instead of an array:

>>> import ctypes
>>> array = ctypes.c_uint32 * 3
>>> class B(ctypes.BigEndianStructure):
...     _fields_ = [("bar", array)]
... 
>>> b = B((1,2,3))
>>> b.bar
<ctypes._endian.c_uint_be_Array_3 object at 0x7f87700798c0>
>>> b.bar[2]
3L
>>> b = B(array(1,2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: incompatible types, c_uint_Array_3 instance instead of 
c_uint_be_Array_3 instance

Oops...

So the only thing that doesn't work transparently is initialising a data 
structure (or at least array) from its "other-endian" twin.






More information about the Python-list mailing list