简体   繁体   English

ctypes bigendianstructure littlendianstructure返回单个字节不同的结果

[英]ctypes bigendianstructure littlendianstructure returns different results for single byte

I am seeing different results when using ctypes and Structure(s) with big and little endian-ness types, and fields with specific bit lengths. 在将ctypes和Structure与大小顺序排列以及具有特定位长的字段一起使用时,我看到不同的结果。 I would expect the bit ordering in a byte to be the same for both endia-ness, but the results are providing different answers. 我希望两个字节的字节顺序是相同的,但是结果提供了不同的答案。 The results are from a centos 6.8 64 bit distro on an intel box. 结果来自intel盒上的centos 6.8 64位发行版。

>>> import ctypes
>>>
>>> class header_struct(ctypes.Structure):
...       _fields_ = [ ('f1',ctypes.c_ubyte,4),
...                    ('f2',ctypes.c_ubyte,4) ]
...
>>> class header_struct_be(ctypes.BigEndianStructure):
...       _fields_ = [ ('f1',ctypes.c_ubyte,4),
...                    ('f2',ctypes.c_ubyte,4) ]
...
>>> class header_struct_le(ctypes.LittleEndianStructure):
...       _fields_ = [ ('f1',ctypes.c_ubyte,4),
...                    ('f2',ctypes.c_ubyte,4) ]
...
>>> a='\x0A'
>>> x=header_struct.from_buffer_copy(a)
>>> x_be=header_struct_be.from_buffer_copy(a)
>>> x_le=header_struct_le.from_buffer_copy(a)
>>>
>>> print " sizeof(x) ", ctypes.sizeof(x)
 sizeof(x)  1
>>> print " sizeof(x_be) ", ctypes.sizeof(x_be)
 sizeof(x_be)  1
>>> print " sizeof(x_le) ", ctypes.sizeof(x_le)
 sizeof(x_le)  1
>>>
>>> x.f1
10
>>> x_be.f1
0
>>> x_le.f1
10
>>>
>>>
>>> x.f2
0
>>> x_be.f2
10
>>> x_le.f2
0
>>>

The bit order inside a byte is not the same for both endianness - of course,in any architecture, you copy a number into a byte, you get back the same byte. 字节内部的字节顺序对于两个字节序都是不同的-当然,在任何体系结构中,您都将数字复制到字节中,然后得到相同的字节。 And in both architectures, the least significant bit is addressed as bit "0". 并且在两种体系结构中,最低有效位都被寻址为位“ 0”。 Since data is moved around in bytes, and this is just emulation, anyway these bit values are not actually mirrored in a x86 architecture in memory. 由于数据是以字节为单位移动的,而这仅仅是仿真,因此这些位值实际上并没有在内存中的x86体系结构中进行镜像。 That is valid for the wat ctypes, and likely, C code you would generate playing along with that do it. 这对于wat ctypes是有效的,并且很可能会产生与此相关的C代码。

However, if you subdivide a byte in fields, the relative position of these fields is mirrored inside the byte - 但是,如果您在字段中细分一个字节,则这些字段的相对位置会在该字节内进行镜像-

You can check that in an easier way using the ctypes.Union construct (that way you also rule out padding-bytes side effects as possible cause of the numbers you see): 您可以使用ctypes.Union构造以更简单的方式进行检查(通过这种方式,您还可以排除padding-bytes的副作用,这可能是导致看到的数字的原因):

import ctypes
class header_struct(ctypes.Structure):
       _fields_ = [ ('f1',ctypes.c_ubyte,4),
                  ('f2',ctypes.c_ubyte,4) ]

class big_endian(ctypes.BigEndianStructure):
      _fields_ = [ ('b{}'.format(i), ctypes.c_ubyte, 1) for i in range(8) ]
class little_endian(ctypes.LittleEndianStructure):
      _fields_ = [ ('b{}'.format(i), ctypes.c_ubyte, 1) for i in range(8) ]

class le_byte(ctypes.LittleEndianStructure):
    _fields_ = [('value', ctypes.c_ubyte)]

class be_byte(ctypes.BigEndianStructure):
    _fields_ = [('value', ctypes.c_ubyte)]

class Union(ctypes.Union):
    _fields_ = [('le', le_byte), ('be', be_byte), ('lebits', little_endian), ('bebits', big_endian)]

And on the interactive console: 在交互式控制台上:

In [319]: u = Union()

In [320]: u.le.value = 0x80

In [321]: u.be.value  # not mirrored
Out[321]: 128

In [322]: u.lebits.b7 
Out[322]: 1

In [323]: u.lebits.b0
Out[323]: 0

In [324]: u.bebits.b7
Out[324]: 0

In [325]: u.bebits.b0
Out[325]: 1

Seeing that you are probably working on some practical code, and not just playing along, my advice would be to keep all structures that have to handle sub-byte fields as LittleEndianStructure, and create an Union with a BigEndianStructure with the same byte-size for whenever you have to copy bytes from the buffer to do your I/O. 看到您可能正在处理一些实用代码,而不仅仅是一起工作,我的建议是将所有必须处理子字节字段的结构都保留为LittleEndianStructure,并为BigEndianStructure创建一个Union,并为它使用相同的字节大小。每当您必须从缓冲区复制字节以执行I / O时。

Putting in another way, just to be sure it is clear: all sub-byte bit maniplation is performed on the structure declared as LittleEndian. 换句话说,只是为了确保它很清楚:所有子字节位操作都在声明为LittleEndian的结构上执行。 Then, to copy multi-byte data to and from this structure, you put it in a union with another structure that only has fields with an integer number of bytes - and which can be declared BigEndian - and perform all the copying of data referencing this other structure. 然后,要在该结构之间来回复制多字节数据,请将其与另一个仅具有整数个字节的字段(可以声明为BigEndian)的结构合并,然后执行所有引用此数据的数据复制其他结构。

Also, do a lot of testing on the whole thing :-). 另外,对整个事情做很多测试:-)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM