2017-03-22 4 views
0

Ich sehe unterschiedliche Ergebnisse, wenn Ctypes und Struktur (en) mit großen und kleinen Endian-Ness-Typen und Feldern mit bestimmten Bitlängen verwendet werden. Ich würde erwarten, dass die Bitordnung in einem Byte für beide Endigungen gleich ist, aber die Ergebnisse liefern unterschiedliche Antworten. Die Ergebnisse stammen von einer Centos 6.8 64 Bit Distribution auf einer Intel Box.ctypes bigendianstructure lindendianstructure gibt verschiedene Ergebnisse für einzelnes Byte zurück

>>> 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 
>>> 
+0

Meh, das sind in der Tat nicht intuitive Ergebnisse Ich frage mich, wer die Frage abgelehnt hat. – jsbueno

Antwort

0

Die Bit-Reihenfolge in einem Byte nicht das gleiche für beide Endian ist - natürlich in jede Architektur, kopieren Sie eine Zahl in ein Byte, erhalten Sie das gleiche Byte zurück. Und in beiden Architekturen wird das niedrigstwertige Bit als Bit "0" adressiert. Da Daten in Bytes verschoben werden und dies nur eine Emulation ist, werden diese Bitwerte sowieso nicht in einer x86-Architektur im Speicher gespiegelt. Das ist gültig für die wat ctypes, und wahrscheinlich, C-Code, den Sie erzeugen würden, wenn Sie damit spielen.

Wenn Sie jedoch ein Byte in den Feldern, die relative Position dieser Felder unterteilen ist innerhalb des Byte gespiegelt -

können Sie, dass der Check in einem einfacheren Weg mit dem ctypes.Union Konstrukt (auf diese Weise auch padding ausschließen -bytes Nebenwirkungen als mögliche Ursache für die Zahlen, die Sie sehen):

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)] 

Und auf der interaktiven Konsole:

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 

Da Sie wahrscheinlich an praktischem Code arbeiten und nicht nur mitspielen, wäre mein Ratschlag, alle Strukturen, die Subbyte-Felder behandeln sollen, als LittleEndianStructure zu behalten und eine Union mit einer BigEndianStructure mit derselben Byte-Größe zu erstellen wann immer Sie Bytes aus dem Puffer kopieren müssen, um Ihre E/A zu tun.

Anders ausgedrückt, nur um sicher zu sein, dass es klar ist: Die gesamte Sub-Byte-Bit-Manipulation wird an der als LittleEndian deklarierten Struktur ausgeführt. Um dann Multibyte-Daten von und zu dieser Struktur zu kopieren, fügen Sie sie in eine Union mit einer anderen Struktur ein, die nur Felder mit einer ganzzahligen Anzahl von Bytes enthält - und die als BigEndian deklariert werden kann - und das Kopieren von Daten, die darauf verweisen andere Struktur.

Auch eine Menge Tests auf die ganze Sache :-).

Verwandte Themen