2012-04-27 34 views
6

我搞了一个二进制数据解析器,虽然我可以回到C上,但我想看看是否可以使用Python来完成任务。如何在Python中正确声明ctype结构+联合?

我有一个如何得到这个正在进行的一些门道,我当前的实现看起来是这样的:

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

其中产生这样的输出:

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 

所以......看来,我就像我的字节不像字词那么多。我不太了解Python或ctypes来理解这是为什么,但目前这种做法有点破坏我的目的。有任何想法吗?

回答

6

您的sHeader有4位字段,然后是2位字段,然后是2位字段(总共8位= 1字节)...但是接下来的项目是c_uint16需要对齐在2字节边界,因此跳过一个字节并在取13位之前移动到字节2。

如果你不希望出现这种情况(显然你不),只是让一切c_uint32或类似:

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 

结果:

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

(我拿起UINT32因为你的位域总共可以达到32位,我在这里使用的是Python 2.7,因此在print上没有括号。)

5

你可以通过_pack_类属性:

class sHeader(Structure): 
    _pack_ = 1 

结果

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

只是尝试这样做的是48位的结构,它很好地工作。 – 2012-05-17 01:03:07