python - 给定映射到 C 结构的字节,如何通过 C 结构的变量名访问字节

标签 python python-3.x

(请耐心等待,我认为是用 C 而不是 Python,所以你可能会看到一些真正愚蠢的东西......)

我有许多(100 多个)不同的 C structs,作为 bytes 被拉入 Python(版本 3.5.1),我希望能够使用原始 C 结构的变量名。这是一个简单的例子。在 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 路径走下去或采取其他方向。

最佳答案

您正在寻找 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!
    )

请注意,您使用乘法运算符定义了一个大小为 nT 类型的数组!:T*n

因此,除了 StructuresArrays 之外,它还支持 Union 和指针,以及为 C 程序员提供的各种好东西.

请注意,您正在使用 bytes 对象,这些对象是不可变的,并且在创建结构时需要一个副本。但是,如果您使用 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'

但是,使用字节数组:

In [16]: buffer = bytearray(example1_bytes)

In [17]: ex2 = Example1.from_buffer(buffer)

In [18]: ex2
Out[18]: <__main__.Example1 at 0x10a5b5598>

In [19]: buffer
Out[19]: bytearray(b'\x08\t\n\x0b')

In [20]: ex2.val2 = 99

In [21]: buffer
Out[21]: bytearray(b'\x08c\n\x0b')

关于python - 给定映射到 C 结构的字节,如何通过 C 结构的变量名访问字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48552043/

相关文章:

python - Matplotlib Pyplot 简单的意大利面条图

python - 使用 aiohttp 的 HEAD 请求很慢

Python:什么是 String[a:b] 的等价物,但对于 Unicode

python - os.fork() 之后的共享对象

python - 将 Python Statsmodel ARIMA 模型参数重新调整为新数据并进行预测

python-3.x - python : mock file input for testing function

python - 按字母顺序查找最长的子串。我的代码有什么问题

python - PySide2 在访问 QObject::property() 时崩溃

python - Pandas 日期时间索引

jquery - 通过 jQuery AJAX 传输数据到 Pyramid 后端问题