如何将 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'