我正在尝试为我在这里创建的类创建一个元类:ctypes variable length structures
我想简化Points类,所以它看起来像这样(Python 3.2):
class Points(c.Structure, metaclass=VariableMeta):
_fields_ = [
('num_points', c.c_uint32),
('points', 'Point*self.num_points')
]
def __init__(self):
self.num_points = 0
self.points = [0,]*MAX_SIZE
这是我到目前为止的元类:
class VariableMeta(type):
def __new__(cls, name, bases, dct):
dct['_inner_fields'] = dct['_fields_']
dct['_fields_'] = [('_buffer', c.c_byte*MAX_PACKET_SIZE)]
return type.__new__(cls, name, bases, dct)
def parse(self):
fields = []
for name, ctype in self._inner_fields:
if type(ctype) == str:
ctype = eval(ctype)
fields.append((name, ctype))
class Inner(c.Structure, PrettyPrinter):
_fields_ = fields
inner = Inner.from_address(c.addressof(self._buffer))
setattr(self, name, getattr(inner, name))
self = inner
return self
def pack(self):
fields = []
for name, ctype in self._inner_fields:
if type(ctype) == str:
ctype = eval(ctype)
fields.append((name, ctype))
class Inner(c.Structure, PrettyPrinter):
_fields_ = fields
inner = Inner()
for name, ctype in self._inner_fields:
value = getattr(self, name)
if type(value) == list:
l = getattr(inner, name)
for i in range(len(l)):
l[i] = getattr(self, name)[i]
else:
setattr(inner, name, value)
return inner
它看起来应该可以工作,但是当我运行它时,我收到错误:TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
。
我搜索了这个问题的解决方案的提示,但是ctypes结构看起来是在c库中实现的。我不确定如何解决这个问题,任何帮助或具体解决方案都表示赞赏!
答案 0 :(得分:4)
问题是ctypes.Structure
使用自己的自定义元类:_ctypes.StructType
。由于您从 Structure 继承了元类,因此Python不知道在构造类时要使用哪个元类。
您可以通过从_ctypes.StructType
继承您的元类来解决此问题。由于元类的名称是 ctypes 模块的实现细节,因此我建议编写type(ctypes.Structure)
以动态获取元类。
import ctypes
class VariableMeta(type(ctypes.Structure)):
pass
这种方法的缺点是限制了元类的使用。如果您只打算将其用于ctypes.Structure
的子类。
另一种方法是创建一个继承自两个元类的中间元类。
class PointsMetaClass(type(ctypes.Structure), VariableMeta):
pass
class Points(c.Structure, metaclass=PointsMetaClass):
# ...
始终确保在您的元类“super()
中使用type
而不是硬编码__new__
!
return super(VariableMeta, cls).__new__(cls, name, bases, dct)
正如Guido曾写道:用Python编写元类will cause your head to explode!