[在python 2.7中使用动态数组创建ctypes通用结构

问题描述 投票:1回答:1

我正在尝试创建具有动态数组行为的ctypes通用结构。我使用以下SO答案作为基础:https://stackoverflow.com/a/42843610/1935787

[当我独立地实例化该类时有效,但是当我将该类用作另一个类的字段时,copy_from_buffer不调用__new__类方法,因此我的类未创建数组。

代码:

import ctypes

class SizedStructure(ctypes.LittleEndianStructure):
   _sized_vars_ = []  # (var_name, var_type, size_var_id, (size_var_path,), size_var_granularity)

   @classmethod
   def from_buffer_copy(cls, buff):
      obj = type(cls).from_buffer_copy(cls, buff)
      values = cls.get_object_sized_vars_values(obj)
      instance = cls.create_inner_struct(values).from_buffer_copy(buff)
      return instance

   @classmethod
   def create_inner_struct(cls, values):
      fields = cls._fields_[:]
      class_name = cls.__name__
      for var_name, var_type, size_var_id, _, size_var_granularity in cls._sized_vars_:
         if size_var_id not in values:
            raise Exception("'{}' not passed".format(size_var_id))
         fields.append((var_name, var_type * (values[size_var_id] * size_var_granularity)))
         class_name = class_name + "_{}_{}".format(size_var_id, values[size_var_id])

      class Temp(ctypes.LittleEndianStructure):
         _pack_ = 1
         _fields_ = fields

         def __init__(self, *args, **kwargs):
            super(Temp, self).__init__(*args, **kwargs)
            for key, value in kwargs.items():
               setattr(self, key, value)

      return type(class_name, (Temp,), {})

   @classmethod
   def get_object_sized_vars_values(cls, obj):
      values = {}
      for _, _, size_var_id, size_var_path, _ in cls._sized_vars_:
         curr = obj
         for part in size_var_path:
            curr = getattr(curr, part)
         values[size_var_id] = curr
      return values

class DynamicLengthArray(SizedStructure):
   _pack_ = 1
   _fields_ = [
         ("size",   ctypes.c_uint32),
      ]
   _sized_vars_ = [("data", ctypes.c_ubyte, "size", ("size",), ctypes.sizeof(ctypes.c_uint8))]

class DynamicLengthArrayParent(ctypes.LittleEndianStructure):
   _pack_ = 1
   _fields_ = [
         ("id",  ctypes.c_uint32),
         ("arr", DynamicLengthArray),
      ]

a = DynamicLengthArray.from_buffer_copy(b"\x02\x00\x00\x00\x33\x44")
assert(a.size == 2)
assert(a.data[0] == 0x33)
assert(a.data[1] == 0x44)
print(a.data)

b = DynamicLengthArrayParent.from_buffer_copy(b"\x78\x56\x34\x12\x02\x00\x00\x00\x33\x44")
assert(b.id == 0x12345678)
assert(b.arr.size == 2)
assert(b.arr.data[0] == 0x33)
assert(b.arr.data[1] == 0x44)
print(b.arr.data) 

结果:

<__main__.c_ubyte_Array_2 object at 0x00000000029EB6C8>
Traceback (most recent call last):
  File "c:/Temp/so.py", line 67, in <module>
    assert(b.arr.data[0] == 0x33)
AttributeError: 'DynamicLengthArray' object has no attribute 'data'

如何通过调用__new__来触发copy_from_buffer方法?

python python-2.7 ctypes
1个回答
0
投票

我也在寻找解决您问题的方法。比

© www.soinside.com 2019 - 2024. All rights reserved.