Hallo zusammen,
ich habe eine eigene Structure mit ein paar Attributen. Diese Structure wird mit Bytes mithilfe der memmove funktion befüllt. Klappt auch wunderbar, allerings sind die Bytes für jedes Attribut nicht in der richtigen Byte reihenfolge. Gibt es eine Möglicheit, dies noch im nachhinein zu ändern und die Bytes ins LittleEndian format zu bringen?
vg, seux
ctypes Strukturen und LittleEndian/BigEndian
Hier mal etwas Code:
Ich habe eine Struktur in dieser Form (kann aber später wesentlich mehr einträge beinhalten). Die Daten lese ich aus einer Datei ein und schiebe sie dann per memmove in die Struktur. wenn ich dann zum beispiel den Namen ausgebe, erhalte ich die 2 Bytes in der falschen reihenfolge. Dies gilt natürlich dann auch für die anderen Einträge.
Wie kann ich nun für jeden Eintrag die Byteorder ändern?
Code: Alles auswählen
class Daten(Structure):
_fields_ = [
('name', c_ulong),
('version', c_ushort),
('data', c_ushort * 10),
]
Wie kann ich nun für jeden Eintrag die Byteorder ändern?
In der Dokumentation gibt es zur Byte Order einen Abschnitt:
Code: Alles auswählen
>>> class Spam(ctypes.Structure):
... _fields_ = ("x", ctypes.c_int),
...
>>> s = Spam(1234567)
>>> str(buffer(s))
'\x87\xd6\x12\x00'
>>>
>>> class Ham(ctypes.BigEndianStructure):
... _fields_ = ("x", ctypes.c_int),
...
>>> h = Ham(1234567)
>>> str(buffer(h))
'\x00\x12\xd6\x87'
Das Leben ist wie ein Tennisball.
@EyDu: Ich lese die Daten ja aus einer Datei ein. Sagen wir mal, ich lese 40 Bytes ein und speichere diese zwischen. laut types() entspricht dies dann einem String. Demnach kann ich das nicht so machen, wie du in deinem Beispiel. An der Stelle erhalte ich, da es sich bei mir um einen String handelt einen TypeError. Deswegen hab ich die Daten auch mit memmove in die Structure geschoben
Code: Alles auswählen
s = Spam(1234567)
Code: Alles auswählen
>>> s = Spam()
>>> h = Ham()
>>> ctypes.memmove(ctypes.addressof(s), '\x87\xd6\x12\x00', 4)
45782448
>>> s.x
1234567
>>> ctypes.memmove(ctypes.addressof(h), '\x87\xd6\x12\x00', 4)
45782304
>>> h.x
-2016013824
Edit: Man kommt doch auch sicher irgendwie ohne das addressof aus, oder?
Das Leben ist wie ein Tennisball.
Ja, genau so, bloß das ich byref() statt adressof() verwende. Aber dein Vorschlag war schon die Lösung muss ich zugeben. Die Lösung mit dem ctypes.BigEndianStructure war doch richtig. Ich war wohl etwas dusselig und hab nicht gemerkt, dass die Bytes schon richtig angeordnet sind. Vielen Dank für die Hilfe
Man könnte auch die `from_buffer_copy()`-Methode auf den Typobjekten verwenden um `memmove()` und `adressof()`/`byref()` und eine redundante Längenangabe zu vermeiden.