Cas*_* K. 7 python byte struct ctypes unions
我正在搞乱制作二进制数据解析器,虽然我可以回到C,但我想看看我是否可以使用Python来完成任务.
我对如何实现这一点有所了解,我当前的实现看起来像这样:
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))
Run Code Online (Sandbox Code Playgroud)
哪个产生这个输出:
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
Run Code Online (Sandbox Code Playgroud)
所以......在我看来,我的字节不是单词,而是单词.我不太了解Python或ctypes来理解它为什么,但它现在正在打败我的目的.有任何想法吗?
你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
Run Code Online (Sandbox Code Playgroud)
结果是:
<Field type=c_uint, ofs=0:8, bits=13>
<Field type=c_uint, ofs=0:24, bits=8>
Run Code Online (Sandbox Code Playgroud)
(我选择了uint32,因为你的位字段加起来是32位.我在这里使用的是Python 2.7,因此prints 上没有括号.)
您可以使用_pack_类属性控制对齐:
class sHeader(Structure):
_pack_ = 1
Run Code Online (Sandbox Code Playgroud)
结果是
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
Run Code Online (Sandbox Code Playgroud)