ctypes Strukturen und LittleEndian/BigEndian

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
seux
User
Beiträge: 10
Registriert: Mittwoch 21. August 2013, 11:17

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
Zuletzt geändert von seux am Mittwoch 4. September 2013, 01:22, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Kannst Du das näher erklären? Bytes sind Bytes, da gibt es keine Endiness.
seux
User
Beiträge: 10
Registriert: Mittwoch 21. August 2013, 11:17

Hier mal etwas Code:

Code: Alles auswählen

class Daten(Structure):
    _fields_ = [
        ('name', c_ulong),
        ('version', c_ushort),
        ('data', c_ushort * 10),
    ]
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?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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.
seux
User
Beiträge: 10
Registriert: Mittwoch 21. August 2013, 11:17

@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

Code: Alles auswählen

s = Spam(1234567)
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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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
Meinst du so?

Edit: Man kommt doch auch sicher irgendwie ohne das addressof aus, oder?
Das Leben ist wie ein Tennisball.
seux
User
Beiträge: 10
Registriert: Mittwoch 21. August 2013, 11:17

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
BlackJack

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.
Antworten