(忍受我,我认为在C而不是Python,所以你可能会看到一些真正愚蠢的东西......)
我有许多(100 +)个不同的C structs
,被引入Python(版本3.5.1)作为bytes
,我希望能够使用原始的C结构访问#39;变量名。这是一个简单的例子。在Python中,我收到了这些bytes
:
# In Python:
example1_bytes = b'\x08\x09\x0a\x0b'
假设这些bytes
由运行C的内容提供,使用以下格式的struct
:
// In C:
struct example1 {
uint8_t val1;
uint8_t val2;
uint8_t val3;
uint8_t val4; };
如何处理example1_bytes
以便我可以像这样访问它们:
# In Python:
result = process_example1_bytes(example1_bytes)
print(result.val1)
# Prints "8"
print(result.val2)
# Prints "9"
# Et cetera
更进一步,如果C struct
更复杂并包含数组和/或子结构,该怎么办?例如,像这样:
// In C:
struct substruct {
uint8_t ss_val1;
uint8_t ss_val2; };
struct example2 {
uint8_t val1;
uint8_t val2;
struct substruct ss[8]; };
如何处理example2_bytes
以便我可以像这样访问它们:
# In Python:
result = process_example2_bytes(example2_bytes)
print(result.val1)
print(result.ss[3].ss_val2)
我使用Python struct
unpack
进行了一些实验,它返回了元组,我认为是向正确方向迈出的一步,但是它还没有让我得到我想要的可用解决方案。我不确定是否需要走namedtuple
路径或采取其他方向。
答案 0 :(得分:3)
您正在寻找ctypes
library,它允许您为复杂的底层C结构定义Python包装器。对于一个简单的类型:
import ctypes
example1_bytes = b'\x08\x09\x0a\x0b'
class Example1(ctypes.Structure):
_fields_ = (
('val1', ctypes.c_uint8),
('val2', ctypes.c_uint8),
('val3', ctypes.c_uint8),
('val4', ctypes.c_uint8)
)
ex1 = Example1.from_buffer_copy(example1_bytes)
print(ex1.val1, ex1.val2, ex1.val3, ex1.val4, sep='|')
# 8|9|10|11
更复杂的结构:
class substruct(ctypes.Structure):
_fields_ = (
('ss_val1', ctypes.c_uint8),
('ss_val2', ctypes.c_uint8),
)
class Example2(ctypes.Structure):
_fields_ = (
('val1', ctypes.c_uint8),
('val2', ctypes.c_uint8),
('ss', substruct*8), #array type!
)
注意,您使用乘法运算符定义大小为T
的{{1}}类型的数组!:n
因此,与T*n
和Structures
一起,它支持Arrays
和指针,以及包含C程序员的各种好东西。
注意,您正在使用Unions
个对象,这些对象是不可变的,在创建结构时需要复制。但是,如果您使用bytes
,则不会需要底层缓冲区的副本!:
bytearray
但是,使用bytearray:
In [4]: example1_bytes
Out[4]: b'\x08\t\n\x0b'
In [5]: ex1.val2 = 99
In [6]: example1_bytes
Out[6]: b'\x08\t\n\x0b'