Parsen von Binärdaten in ctypes Structure-Objekt über readinto ()

Ich versuche, ein binäres Format zu verarbeiten, indem ich dem folgenden Beispiel folge:

http://dabeaz.blogspot.jp/2009/08/python-binary-io-handling.html

>>> from ctypes import *
>>> class Point(Structure):
>>>     _fields_ = [ ('x',c_double), ('y',c_double), ('z',c_double) ]
>>>
>>> g = open("foo","rb") # point structure data
>>> q = Point()
>>> g.readinto(q)
24
>>> q.x
2.0

Ich habe eine Struktur meines Headers definiert und ich versuche, Daten in meine Struktur einzulesen, aber ich habe einige Schwierigkeiten. Meine Struktur ist wie folgt:

class BinaryHeader(BigEndianStructure):
    _fields_ = [
                ("sequence_number_4bytes", c_uint),
                ("ascii_text_32bytes", c_char),
                ("timestamp_4bytes", c_uint),
                ("more_funky_numbers_7bytes", c_uint, 56),
                ("some_flags_1byte", c_byte),
                ("other_flags_1byte", c_byte),
                ("payload_length_2bytes", c_ushort),

                ] 

Dasctypes Dokumentation sagt:

Für Felder vom Typ Ganzzahl wie c_int kann ein drittes optionales Element angegeben werden. Es muss eine kleine positive Ganzzahl sein, die die Bitbreite des Feldes definiert.

So für("more_funky_numbers_7bytes", c_uint, 56), Ich habe versucht, das Feld als 7-Byte-Feld zu definieren, erhalte jedoch den Fehler:

ValueError: Anzahl der ungültigen Bits für das Bitfeld

Mein erstes Problem ist also, wie kann ich ein 7-Byte-Int-Feld definieren?

Wenn ich dieses Problem überspringe und das Feld "more_funky_numbers_7bytes" auskommentiere, werden die resultierenden Daten in geladen. Wie erwartet wird jedoch nur 1 Zeichen in "ascii_text_32bytes" geladen. Und aus irgendeinem Grund kehrt zurück16 Ich gehe davon aus, dass dies die berechnete Anzahl von Bytes ist, die in die Struktur eingelesen wurden ... Aber wenn ich mein "funky number" -Feld auskommentiere und "ascii_text_32bytes" nur ein Zeichen (1 Byte) angibt, sollte das nicht sein 13, nicht 16 ???

Dann habe ich versucht, das char-Feld in eine separate Struktur aufzuteilen und auf diese innerhalb meiner Header-Struktur zu verweisen. Aber das funktioniert auch nicht ...

class StupidStaticCharField(BigEndianStructure):
    _fields_ = [
                ("ascii_text_1", c_byte),
                ("ascii_text_2", c_byte),
                ("ascii_text_3", c_byte),
                ("ascii_text_4", c_byte),
                ("ascii_text_5", c_byte),
                ("ascii_text_6", c_byte),
                ("ascii_text_7", c_byte),
                ("ascii_text_8", c_byte),
                ("ascii_text_9", c_byte),
                ("ascii_text_10", c_byte),
                ("ascii_text_11", c_byte),
                .
                .
                .
                ]

class BinaryHeader(BigEndianStructure):
    _fields_ = [
                ("sequence_number_4bytes", c_uint),
                ("ascii_text_32bytes", StupidStaticCharField),
                ("timestamp_4bytes", c_uint),
                #("more_funky_numbers_7bytes", c_uint, 56),
                ("some_flags_1byte", c_ushort),
                ("other_flags_1byte", c_ushort),
                ("payload_length_2bytes", c_ushort),

                ] 

Also, irgendwelche Ideen, wie man:

Definiere ein 7 Byte Feld (welches ich mit einer definierten Funktion dekodieren muss)Definieren Sie ein statisches Zeichenfeld von 32 Bytes

AKTUALISIEREN

Ich habe eine Struktur gefunden, die zu funktionieren scheint ...

class BinaryHeader(BigEndianStructure):
    _fields_ = [
                ("sequence_number_4bytes", c_uint),
                ("ascii_text_32bytes", c_char * 32),
                ("timestamp_4bytes", c_uint),
                ("more_funky_numbers_7bytes", c_byte * 7),
                ("some_flags_1byte", c_byte),
                ("other_flags_1byte", c_byte),
                ("payload_length_2bytes", c_ushort),

                ]  

Jetzt ist jedoch meine verbleibende Frage, warum bei der Verwendung.readinto():

f = open(binaryfile, "rb")

mystruct = BinaryHeader()
f.readinto(mystruct)

Es kehrt zurück52 und nicht das erwartete,51. Woher kommt dieses zusätzliche Byte und wohin geht es?

UPDATE 2 Für Interessierte hier einBeispiel einer Alternativestruct Methode zum Einlesen von Werten in ein von eryksun genanntes namedtuple:

>>> record = 'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name='raymond   ', serialnum=4658, school=264, gradelevel=8)

Antworten auf die Frage(1)

Ihre Antwort auf die Frage