如何将ctypes转换为字节

问题描述 投票:0回答:1

我想访问我定义的 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选项。

python python-3.x ctypes
1个回答
5
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.