【问题标题】:How can I create this struct?我怎样才能创建这个结构?
【发布时间】:2022-10-24 07:51:52
【问题描述】:

我想创建一个这样的结构:

import ctypes

class MyStruct(ctypes.Structure):
    _fields_ = [('field1', /* size of 16 bytes */),
                ('field2', /* size of 4 bytes */)
                ('field3', /* size of 8 bytes */)]

对于这些大小的字段,我需要在这里写什么类型?我希望field1 的最大大小为 16 个字节,因此所需的值将被写入那里,并且所有其他字节将为零(如有必要,最多 16 个字节)。对于field2field3 也是如此。

【问题讨论】:

  • 你想如何使用这个结构?
  • 例如,ctypes.c_char * 16,如果你想在 C 中与 char field1[16] 等效。最好展示你在 C 中对结构所做的操作。
  • 你不需要ctypes 来使用struct.pack。例如,struct.pack('>16sLQ',bytes(range(16)),1,5) 将创建一个具有 16 字节、4 字节无符号整数和 8 字节无符号整数的 bytes 字符串。
  • 没有一个 16 字节的整数,所以你必须做一些事情,比如分成两个 c_uint64 字段,或者使用 n.to_bytes(16,'little') 来生成 n 的 16 字节 little-endian 值。
  • @OlvinR​​oght 取决于操作系统而不是可移植的。在 Windows 上,ctypes.c_longdouble 的大小为 8。

标签: python struct ctypes


【解决方案1】:

两种方式。 16 位字段使它有点棘手:

import ctypes

class MyStruct(ctypes.Structure):
    _pack_ = 1
    _fields_ = (('field1', ctypes.c_ubyte * 16), # C char[16] field1
                ('field2', ctypes.c_uint32),     # C uint32_t field2
                ('field3', ctypes.c_uint64))     # C uint64_t field3
    def __init__(self,a,b,c):
        self.field1[:] = a.to_bytes(16,'little') # [:] trick to copy bytes to c_ubyte array
        self.field2 = b
        self.field3 = c

s = MyStruct(0x100, 0x200, 0x300)
print(bytes(s).hex(' '))

with open('out.bin','wb') as f:
    f.write(bytes(s))

或者

import struct

b = struct.pack('<16sLQ',(0x100).to_bytes(16,'little'),0x200,0x300)
print(b.hex(' '))

with open('out.bin','wb') as f:
    f.write(b)

输出:

00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 00 00 00
00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 00 00 00

【讨论】:

  • 你能解释一下_pack_ = 1 的意思吗?另外,如果我想将它(结构)写入二进制文件,我该怎么做?
  • @user20007266 如果成员不在对齐的地址边界上,C 结构会插入填充字节(8 字节整数必须从 8 字节偏移量开始)。 field3 的偏移量为 20,不能被 8 整除,因此将在 field2field3 之间添加 4 个字节的填充,而不指示打包应尽可能使用 _pack_=1(默认为 8)。我将编辑以显示写入文件。
  • 多字节整数可以通过两种方式存储在内存中。四字节整数 0x12345678 可以大端存储,或者内存中的高字节到低字节(12 34 56 78)或内存中低字节到高字节的小端(78 56 34 12)。 Intel 处理器使用 little-endian。请参阅int.to_bytes 的文档。根据您的用例,您可能希望使用'big'(或struct.pack 中的&gt;)。
  • @user20007266 &gt;(或&lt;)不强制对齐,因此与_pack_=1 相同。阅读docs
  • @user20007266 实验!尝试使用 0x1234 而不是 0x100。我只是解释了小端序。将其更改为 &gt;'big' 以查看差异。
猜你喜欢
  • 2017-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 2017-07-06
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多