2012-04-27 32 views
6

Tôi đang rối tung xung quanh với việc tạo một trình phân tích cú pháp dữ liệu nhị phân và trong khi tôi có thể quay trở lại C, tôi muốn xem liệu tôi có thể sử dụng Python cho tác vụ hay không.Làm cách nào để khai báo chính xác cấu trúc ctype + Liên kết bằng Python?

Tôi có một số ý niệm mơ hồ về cách để có được đi này, và thực hiện hiện tại của tôi trông giống như sau:

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

nào sản xuất sản lượng này:

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 

Vì vậy ... Có vẻ đối với tôi như byte của tôi không phải là byte nhiều như từ. Tôi không biết đủ về Python hoặc ctypes để hiểu tại sao đó là, nhưng đó là loại đánh bại mục đích của tôi vào lúc này. Ý tưởng nào?

Trả lời

6

sHeader có trường 4 bit, sau đó trường 2 bit, sau đó là trường 2 bit (tổng 8 bit = 1 byte) ... nhưng sau đó mục tiếp theo là c_uint16 cần được căn chỉnh trên 2 -byte ranh giới và do đó bỏ qua một byte và di chuyển đến byte 2 trước khi lấy 13 bit.

Nếu bạn không muốn điều đó (và dường như bạn không), chỉ cần làm cho mọi thứ một c_uint32 hoặc tương tự:

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 

kết quả trong:

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

(Tôi nhặt uint32 vì các trường bit của bạn thêm tối đa 32 bit. Tôi đang sử dụng Python 2.7 tại đây, do đó không có dấu ngoặc đơn trên print s.)

5

Bạn có thể kiểm soát căn chỉnh với _pack_ lớp thuộc tính:

class sHeader(Structure): 
    _pack_ = 1 

kết quả trong

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

Chỉ cần cố gắng này trên một cấu trúc đó là 48 bit, và nó hoạt động độc đáo. –

Các vấn đề liên quan