2012-04-27 20 views
6

Piszę dookoła z tworzeniem binarnego parsera danych i gdybym mógł wrócić do C, chciałem sprawdzić, czy mogę użyć Pythona do zadania.Jak prawidłowo opisać strukturę typu + Union w języku Python?

mam pewne pojęcie o tym, jak dostać się dzieje, a moja obecna implementacja wygląda mniej więcej tak:

from ctypes import * 

class sHeader(Structure): 
    _fields_ = [("CC", c_uint8, 4), 
      ("AFC", c_uint8, 2), 
      ("TSC", c_uint8, 2), 
      ("PID", c_uint16, 13), 
      ("TP", c_uint16, 1), 
      ("PSI", c_uint16, 1), 
      ("TEI", c_uint16, 1), 
      ("SyncByte", c_uint8)] 

class Header(Union): 
    _fields_ = [("sData", sTsHeader), 
      ("ulData", c_uint32)] 

head = Header() 
head.ulData = 0xffffffff 
print(head.ulData) 
print(head.sData.SyncByte) 

print(sHeader.SyncByte) 
print(sHeader.TEI) 
print(sHeader.PSI) 
print(sHeader.TP) 
print(sHeader.PID) 
print(sHeader.TSC) 
print(sHeader.AFC) 
print(sHeader.CC) 


print(sizeof(sHeader)) 
print(sizeof(c_uint8)) 
print(sizeof(c_uint16)) 
print(sizeof(c_uint32)) 

która produkuje ten wyjściowe:

V:\>C:\Python27\python.exe WidiUnpacker.py 
0xffffffffL 
0x0 
<Field type=c_ubyte, ofs=4, size=1> 
<Field type=c_ushort, ofs=2:15, bits=1> 
<Field type=c_ushort, ofs=2:14, bits=1> 
<Field type=c_ushort, ofs=2:13, bits=1> 
<Field type=c_ushort, ofs=2:0, bits=13> 
<Field type=c_ubyte, ofs=0:6, bits=2> 
<Field type=c_ubyte, ofs=0:4, bits=2> 
<Field type=c_ubyte, ofs=0:0, bits=4> 
6 
1 
2 
4 

Więc ... wygląda mi podobnie jak moje bajty nie są bajtami tak bardzo jak słowami. Nie wiem wystarczająco dużo o Pythonie lub ctypach, aby zrozumieć, dlaczego tak jest, ale to w pewnym sensie niweczy mój cel. Jakieś pomysły?

Odpowiedz

6

Twoje ma pole 4-bitowe, a następnie 2-bitowe, a następnie 2-bitowe (łącznie 8 bitów = 1 bajt) ... ale następny element to c_uint16, który należy wyrównać na 2 -byte granice, a zatem przeskakuje bajt i przechodzi do bajtu 2 przed pobraniem 13 bitów.

Jeśli nie chcesz, że (i najwyraźniej nie), tylko zrobić wszystko, c_uint32 lub podobne:

from ctypes import * 

class sHeader(Structure): 
    _fields_ = [("CC", c_uint32, 4), 
     ("AFC", c_uint32, 2), 
     ("TSC", c_uint32, 2), 
     ("PID", c_uint32, 13), 
     ("TP", c_uint32, 1), 
     ("PSI", c_uint32, 1), 
     ("TEI", c_uint32, 1), 
     ("SyncByte", c_uint32, 8)] # note: added 8 here 

print sHeader.PID 
print sHeader.SyncByte 

skutkuje:

<Field type=c_uint, ofs=0:8, bits=13> 
<Field type=c_uint, ofs=0:24, bits=8> 

(bo wybrałem uint32 twoje pola bitowe dodają do 32 bitów. Używam tutaj Python 2.7, dlatego nie ma nawiasów na print s.)

5

Możesz kontrolować wyrównanie za pomocąatrybut 210 Klasa:

class sHeader(Structure): 
    _pack_ = 1 

skutkuje

4294967295 
255 
<Field type=c_ubyte, ofs=3, size=1> 
<Field type=c_ushort, ofs=1:15, bits=1> 
<Field type=c_ushort, ofs=1:14, bits=1> 
<Field type=c_ushort, ofs=1:13, bits=1> 
<Field type=c_ushort, ofs=1:0, bits=13> 
<Field type=c_ubyte, ofs=0:6, bits=2> 
<Field type=c_ubyte, ofs=0:4, bits=2> 
<Field type=c_ubyte, ofs=0:0, bits=4> 
4 
1 
2 
4 
+0

prostu próbowałem to na konstrukcji, która wynosi 48 bitów, i to działa dobrze. –

Powiązane problemy