该行定义实际上是用于定义位域的:
...("more_funky_numbers_7bytes", c_uint, 56),...这是错的。位字段的大小应小于或等于类型的大小,因此
c_uint最多应为32,多一位会引发异常:
ValueError: number of bits invalid for bit field
使用位域的示例:
from ctypes import *class MyStructure(Structure): _fields_ = [ # c_uint8 is 8 bits length ('a', c_uint8, 4), # first 4 bits of `a` ('b', c_uint8, 2), # next 2 bits of `a` ('c', c_uint8, 2), # next 2 bits of `a` ('d', c_uint8, 2), # since we are beyond the size of `a` # new byte will be create and `d` will # have the first two bits ]mystruct = MyStructure()mystruct.a = 0b0000mystruct.b = 0b11mystruct.c = 0b00mystruct.d = 0b11v = c_uint16()# copy `mystruct` into `v`, I use Windowscdll.msvcrt.memcpy(byref(v), byref(mystruct), sizeof(v))print sizeof(mystruct) # 2 bytes, so 6 bits are left floating, you may # want to memset with zerosprint bin(v.value) # 0b1100110000您需要的是7个字节,因此最终所做的操作是正确的:
...("more_funky_numbers_7bytes", c_byte * 7),...至于结构的大小,它将是52,我将填充额外的字节以使结构在32位处理器上的4字节或64位上的8字节对齐。这里:
from ctypes import *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), ]mystruct = BinaryHeader( 0x11111111, 'x22' * 32, 0x33333333, (c_byte * 7)(*([0x44] * 7)), 0x55, 0x66, 0x7777)print sizeof(mystruct)with open('data.txt', 'wb') as f: f.write(mystruct)多余的字节在文件之间
other_flags_1byte和
payload_length_2bytes中进行填充:
00000000 11 11 11 11 ....00000004 22 22 22 22 """"00000008 22 22 22 22 """"0000000C 22 22 22 22 """"00000010 22 22 22 22 """"00000014 22 22 22 22 """"00000018 22 22 22 22 """"0000001C 22 22 22 22 """"00000020 22 22 22 22 """"00000024 33 33 33 33 333300000028 44 44 44 44 DDDD0000002C 44 44 44 55 DDDU00000030 66 00 77 77 f.ww ^ extra byte
当涉及文件格式和网络协议时,这是一个问题。要更改它,请按1打包:
...class BinaryHeader(BigEndianStructure): _pack_ = 1 _fields_ = [ ("sequence_number_4bytes", c_uint),...该文件将是:
00000000 11 11 11 11 ....00000004 22 22 22 22 """"00000008 22 22 22 22 """"0000000C 22 22 22 22 """"00000010 22 22 22 22 """"00000014 22 22 22 22 """"00000018 22 22 22 22 """"0000001C 22 22 22 22 """"00000020 22 22 22 22 """"00000024 33 33 33 33 333300000028 44 44 44 44 DDDD0000002C 44 44 44 55 DDDU00000030 66 77 77 fww
至于
struct,这不会使您的情况变得更容易。可悲的是,它不支持该格式的嵌套元组。例如这里:
>>> from struct import *>>>>>> data = 'x11x11x11x11x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x22x33x33x33x33x44x44x44x44x44x44x44x55x66x77x77'>>>>>> BinaryHeader = Struct('>I32cI7BBBH')>>>>>> BinaryHeader.unpack(data)(286331153, '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', 858993459, 68, 68, 68, 68, 68, 68, 68, 85, 102, 30583)>>>无法使用此结果
namedtuple,您仍然可以根据索引对其进行解析。如果您可以做类似的事情,那将会起作用
'>I(32c)(I)(7B)(B)(B)H'。自2003年以来,就一直要求使用此功能(扩展struct.unpack以生成嵌套元组),但是此后什么也没做。



