[issue24859] ctypes.Structure bit order is reversed - counts from right
eryksun added the comment: No, ctypes.Structure should use native endianness. So on a little-endian it's the same as ctypes.LittleEndianStructure, and on a big-endian system it's the same as ctypes.BigEndianStructure. ARM processors can work in either mode. IIRC, the Raspberry Pi is built as a little-endian system. Check sys.byteorder to be sure. -- stage: - resolved ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue24859 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24859] ctypes.Structure bit order is reversed - counts from right
eryksun added the comment: It seems you want a BigEndianStructure: from ctypes import * class SAEJ1939MsgId(BigEndianStructure): _fields_ = (('reserved', c_uint8, 3), ('priority', c_uint8, 3), ('extended_data_page', c_uint8, 1), ('data_page', c_uint8, 1), ('pdu_format', c_uint8), ('pdu_specific', c_uint8), ('source_address', c_uint8)) def __init__(self, *args, pgn=0, **kwds): super().__init__(*args, **kwds) if pgn 0: self.pgn = pgn def __int__(self): return int.from_bytes(self, 'big') @property def pgn(self): pgn is an 18-bit number consisting of EDP, DP, PF, and PS return (int(self) 8) 0x3 @pgn.setter def pgn(self, value): value |= self.priority 18 view = (c_char * 3).from_buffer(self) view[:] = value.to_bytes(3, 'big') @classmethod def from_bytes(cls, msg_id): return cls.from_buffer_copy(msg_id) @classmethod def from_integer(cls, msg_id): msg_id_bytes = msg_id.to_bytes(sizeof(cls), 'big') return cls.from_buffer_copy(msg_id_bytes) Example: a = SAEJ1939MsgId(priority=7, source_address=3) hex(int(a)) '0x1c03' b = SAEJ1939MsgId(pgn=0xf004, priority=7, source_address=3) hex(int(b)) '0x1cf00403' b.priority 7 b.pdu_format 240 b.pdu_specific 4 b.source_address 3 c = SAEJ1939MsgId.from_integer(int(b)) hex(int(c)) '0x1cf00403' -- nosy: +eryksun ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue24859 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24859] ctypes.Structure bit order is reversed - counts from right
zeero added the comment: Thanks for the advise. I'll give it a try. So ctypes.Structure is always little endian regardless from the underlying architecture. I just checked on a raspberry pi 2 that should be a big endian device, and got the same results as before. I'm still not sure if it's right that ctypes.Structure swaps the order of the bit items but apparently it's the intended behaviour. I'll close the issue then. Thanks again. -- resolution: - not a bug status: open - closed ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue24859 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24859] ctypes.Structure bit order is reversed - counts from right
zeero added the comment: Sorry for the inconvenience. The format specification can be found in chapter 2.1 in http://vector.com/portal/medien/cmc/application_notes/AN-ION-1-3100_Introduction_to_J1939.pdf So I would write down the field contents in that order _fields_ = [('reserved',c_uint8,3), ('priority',c_uint8,3), ('extended_data_page',c_uint8,1), ('data_page',c_uint8,1) ... ] I expect the first Byte to be 0x1C when I set priority to 7 but it came out as 0x38, after tunneling it through the Union object. Reversing the order of the bit fields makes it work like expected. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue24859 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24859] ctypes.Structure bit order is reversed - counts from right
Martin Panter added the comment: It would be helpful if you could trim down your example code a bit. Without studying the whole file, it is hard to see exactly what order you are seeing and what order you expect, since there are two versions with different orders in the code. My understanding of the “ctypes” module is that it is for interacting with the local OS, ABI, compiler, etc, which could use various layouts depending on the platform. According to the Linux x86-64 ABI http:/www.x86-64.org/documentation/abi.pdf, page 14, “bit-fields are allocated from right to left”, which I interpret to mean from least-significant to most-significant bit. Not so sure about Windows, but https://msdn.microsoft.com/en-us/library/yszfawxh.aspx suggests a similar story (LSB first). This behaviour agrees with my experiments on Linux and Wine: class Bitfield(Structure): ... _fields_ = ((a, c_uint8, 4), (b, c_uint8, 4)) ... bytes(Bitfield(0xA, 0xB)) b'\xba' Does this agree with what you expect? Otherwise, what leads you to expect something different? Also: * bytes(saej1939_message_id) should copy the bytes directly; no need for a union. * struct.unpack() should also accept a “ctypes” object directly; no need for the copy. -- nosy: +martin.panter ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue24859 ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com