[issue24859] ctypes.Structure bit order is reversed - counts from right

2015-08-15 Thread eryksun

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

2015-08-15 Thread eryksun

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

2015-08-15 Thread zeero

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

2015-08-14 Thread zeero

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

2015-08-13 Thread Martin Panter

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