ctypes.Structure: string of bytes to Structure

ctypes.Structure: string of bytes to Structure

我想弄清楚如何将 test_data 打包到 TestInfo

from ctypes import Structure, c_char, c_uint8


class TestInfo(Structure):
    _fields_ = [
        ('version', c_uint8),
        ('lsbyte', c_uint8),
        ('msbyte', c_uint8),
        ('free_space', c_uint8 * 2),
        ('recent_addtime', c_uint8 * 4),
        ('recent_erasetime', c_uint8 * 4),
        ('operation_support', c_uint8)
    ]
test_data = '51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a'

应该这样包装

TestInfo.version = 0x51
TestInfo.lsbyte  = 0xaf
...
...
TestInfo.recent_erasetime = 0xf400c760
TestInfo.operation_support = 0x0a

您可以使用以下内容:

import ctypes as ct

class TestInfo(ct.BigEndianStructure):
    _pack_ = 1
    _fields_ = [('version', ct.c_uint8),
                ('lsbyte', ct.c_uint8),
                ('msbyte', ct.c_uint8),
                ('free_space', ct.c_uint16),
                ('recent_addtime', ct.c_uint32),
                ('recent_erasetime', ct.c_uint32),
                ('operation_support', ct.c_uint8)]

    def __repr__(self):
        return (f'TestInfo(version={self.version:#02x}, lsbyte={self.lsbyte:#02x}, ' \
               f'msbyte={self.msbyte:#02x}, free_space={self.free_space:#04x}, ' \
               f'recent_addtime={self.recent_addtime:#08x}, ' \
               f'recent_erasetime={self.recent_erasetime:#08x}, ' \
               f'operation_support={self.operation_support:#02x})')

test_data = bytes.fromhex('51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a')
test_info = TestInfo.from_buffer_copy(test_data)
print(test_info)

输出:

TestInfo(version=0x51, lsbyte=0xaf, msbyte=0x1, free_space=0x65, recent_addtime=0xf152ff60, recent_erasetime=0xf400c760, operation_support=0xa)

如果不将此结构传递给 C 代码,另一个选项是使用 structnamedtuple 模块。

import struct
from collections import namedtuple

TestInfo = namedtuple('TestInfo','version lsbyte msbyte free_space recent_addtime recent_erasetime operation_support')

test_data = bytes.fromhex('51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a')
test_info = TestInfo(*struct.unpack('>BBBHLLB',test_data))
print(test_info)
print(hex(test_info.recent_erasetime))

输出(十进制值等价,打印一个验证):

TestInfo(version=81, lsbyte=175, msbyte=1, free_space=101, recent_addtime=4048748384, recent_erasetime=4093691744, operation_support=10)
0xf400c760