我想访问我定义的 ctype.Structure,作为 Python 中的字节(
b''
)。
我不知道这是正确的方法吗?我需要将标头(它应该与架构无关)发送到其他设备。
所以我将其定义为:
class Header(ctypes.Structure):
_pack_ = 2
_fields_ = [
('version', c_uint8),
('additional_options', c_uint8),
('soft_version', c_uint16),
('compilation_time', c_uint8 * 6),
('crc', c_uint16)
]
现在我需要计算CRC。从
version
开始到 compilation_time
我有一个处理字节的函数。
所以对我来说,只需将 ctypes.Structure 转换为字节(b'')或直接访问内存并更改最后两个字节就可以了。
我尝试使用struct,但没有找到pragma选项。
struct
就是你想要的:
import struct
from binascii import crc32
fmt = struct.Struct('<BBH6s')
data = struct.pack('<BBH6s', 1, 2, 3, b'170207')
print(data)
print(data.hex(' '))
crc = 0xABCD # <do your calculation here>
data += struct.pack('<H',crc)
print(data)
print(data.hex(' '))
<
表示打包小端字节序,不会像 C 那样添加填充字节,因此不需要 _pack_
。 如果您需要大尾数,请使用 >
代替。
我使用了
6s
并传递了一个适合您时间的正确长度的字节字符串。 如果您想传递原始字节,请使用 6B
并列出 6 个字节而不是一个字符串。
输出:
b'\x01\x02\x03\x00170207'
01 02 03 00 31 37 30 32 30 37
b'\x01\x02\x03\x00170207\xcd\xab'
01 02 03 00 31 37 30 32 30 37 cd ab
这是一个
ctypes
解决方案。 我使用了 crc32
,因为库中有一个可用于演示目的。
import ctypes as ct
from binascii import crc32
class Header(ct.LittleEndianStructure):
_pack_ = 1 # prevent alignment padding
_fields_ = (('version', ct.c_uint8),
('additional_options', ct.c_uint8),
('soft_version', ct.c_uint16),
('compilation_time', ct.c_uint8 * 6),
('crc', ct.c_uint32))
h = Header(1, 2, 3)
h.compilation_time[:] = b'ABCDEF' # use slicing to copy into an array
b = bytes(h)[:Header.crc.offset] # convert struct to bytes and truncate CRC
print(b)
h.crc = crc32(b) # Set the correct CRC
b = bytes(h) # convert whole struct to bytes
print(b)
print(b.hex(' '))
输出:
b'\x01\x02\x03\x00ABCDEF'
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6'
01 02 03 00 41 42 43 44 45 46 e7 73 85 a6