如何将 ctypes 转换为字节
How to convert ctypes to bytes
我想访问 ctype.Structure 我已经定义为 Python (b''
) 中的一个字节。
我不知道这是正确的方法吗?我需要向其他设备发送 header(它应该是无架构的)。
所以我将其定义为:
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
>>> fmt = struct.Struct('<BBH6s')
>>> data = fmt.pack(1,2,3,b'170207')
>>> data
b'\x01\x02\x03\x00170207'
>>> crc = <do your calculation>
>>> data += struct.pack('<H',crc)
<
意味着 pack little-endian 并且不会像 C 那样添加填充字节,所以不需要 _pack_
。如果您需要大端,请改用 >
。
我使用了 6s
并根据您的时间传递了正确长度的字节字符串。如果您想传递原始字节而不是使用 6B
并列出 6 个字节而不是一个字符串。
这是一个 ctypes 解决方案。我使用了 crc32,因为库中有一个用于演示目的。
from ctypes import *
from binascii import crc32
class Header(Structure):
_pack_ = 2
_fields_ = [
('version', c_uint8),
('additional_options', c_uint8),
('soft_version', c_uint16),
('compilation_time', c_uint8 * 6),
('crc', c_uint32)
]
h = Header(1,2,3)
h.compilation_time = (c_uint8 * 6)(*b'ABCDEF')
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)
输出:
b'\x01\x02\x03\x00ABCDEF'
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6'
我想访问 ctype.Structure 我已经定义为 Python (b''
) 中的一个字节。
我不知道这是正确的方法吗?我需要向其他设备发送 header(它应该是无架构的)。
所以我将其定义为:
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
>>> fmt = struct.Struct('<BBH6s')
>>> data = fmt.pack(1,2,3,b'170207')
>>> data
b'\x01\x02\x03\x00170207'
>>> crc = <do your calculation>
>>> data += struct.pack('<H',crc)
<
意味着 pack little-endian 并且不会像 C 那样添加填充字节,所以不需要 _pack_
。如果您需要大端,请改用 >
。
我使用了 6s
并根据您的时间传递了正确长度的字节字符串。如果您想传递原始字节而不是使用 6B
并列出 6 个字节而不是一个字符串。
这是一个 ctypes 解决方案。我使用了 crc32,因为库中有一个用于演示目的。
from ctypes import *
from binascii import crc32
class Header(Structure):
_pack_ = 2
_fields_ = [
('version', c_uint8),
('additional_options', c_uint8),
('soft_version', c_uint16),
('compilation_time', c_uint8 * 6),
('crc', c_uint32)
]
h = Header(1,2,3)
h.compilation_time = (c_uint8 * 6)(*b'ABCDEF')
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)
输出:
b'\x01\x02\x03\x00ABCDEF'
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6'