gpt4 book ai didi

具有灵活数组成员的 Python ctypes 结构到 bytearray

转载 作者:行者123 更新时间:2023-12-05 06:11:45 24 4
gpt4 key购买 nike

我正在编写一个将写入二进制文件的 Python 应用程序。该文件将由在嵌入式目标上运行的一些 C 代码进行解析。

我相信我可以通过从 Struct class 派生来做到这一点,但是打包格式很糟糕,而且我所有的结构都是小端,所以我想到了使用 ctypes 包。

假设我有以下 C 结构:

struct my_c_struct
{
uint32_t a;
uint16_t b;
uint16_t table[];
};

在 C 端,我使用转换为内存缓冲区的指针对该结构进行操作,因此我可以:

uint8_t buf[128];
struct my_c_struct *p = (struct my_c_struct*) buf;
p->table[0] = 0xBEEF;

如何在 Python 中最好地表示它?我的第一个尝试是:

class MyCStruct(ctypes.LittleEndianStructure):

c_uint32 = ctypes.c_uint32
c_uint16 = ctypes.c_uint16

_pack_ = 1

_fields_ = [
("a", c_uint32),
("b", c_uint16),
]

def __init__(self, a, b):
"""
Constructor
"""
super(ctypes.LittleEndianStructure, self).__init__(a, b)
self.table = []

def pack(self):
data = bytearray(self.table)
return bytearray(self)+data

pack() 方法背后的想法是它将在结构的末尾组装可变长度表。请注意,我不知道 table 在创建对象时有多少条目。

我实现的方式显然行不通。所以我在考虑将 ctypes-devived 类嵌套在一个纯 Python 类中:

class MyCStruct:

class my_c_struct(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [ ("a", ctypes.c_uint32),
("b", ctypes.c_uint16) ]


def __init__(self, a, b):
"""
Constructor
"""
self.c_struct = self.my_c_struct(a,b)
self.table = []

def pack(self):
self.c_struct.b = len(self.table)
x = bytearray(self.c_struct)
y = bytearray()
for v in self._crc_table:
y += struct.pack("<H", v)
return x + y

这样做的好方法吗?我不想为了发现有更好的方法而深入兔子洞。

警告:我正在使用 Python 2(请不要问...),因此仅 Python 3 的解决方案对我没有用,但对宇宙的其他人有用。

干杯!

最佳答案

struct 模块对于这个问题真的很容易使用(Python 2 代码):

>>> import struct
>>> a = 1
>>> b = 2
>>> table = [3,4]
>>> struct.pack('<LH{}H'.format(len(table)),a,b,*table)
'\x01\x00\x00\x00\x02\x00\x03\x00\x04\x00'

使用.format将16位值的长度插入到table中,使用*table展开table 转换为正确数量的参数。

ctypes 做这个更复杂。此函数声明一个具有正确可变数组大小的自定义结构并填充它,然后生成原始数据字节的字节字符串:

#!python2
from ctypes import *

def make_var_struct(a,b,table):
class Struct(Structure):
_pack_ = 1
_fields_ = (('a',c_uint32),
('b',c_uint16),
('table',c_uint16 * len(table)))
return Struct(a,b,(c_uint16*len(table))(*table))

s = make_var_struct(1,2,[3,4])
print(repr(''.join(buffer(s))))

输出:

'\x01\x00\x00\x00\x02\x00\x03\x00\x04\x00'

关于具有灵活数组成员的 Python ctypes 结构到 bytearray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63853622/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com