我在Python 3.2.2中使用ctypes来封装一些C数据结构。最终目标是能够在结构的数据时有一个包装C结构通知的对象 内容已被修改。
代表性代码:
from ctypes import *
class Comm(Structure):
def __init__(self):
self.attributes_updated = False
def __setattr__(self, name, value):
super(Comm, self).__setattr__('attributes_updated', True)
super(Comm, self).__setattr__(name, value)
class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', c_int*5)]
def __init__(self):
Comm.__init__(self)
这适用于任何简单的数据属性,例如'number'。
>>> s = MyCStruct()
>>> s.attributes_updated
False
>>> s.value = 123
>>> s.attributes_updated
True
由于未通过索引表示法访问__setattr__
进行访问
array
属性,因此我希望覆盖作为数组的C结构成员的__setitem__
属性。据推测,此时我需要将一个引用包含在包含对象中,以便可以更改包含对象的attributes_updated
变量,但是我还没有达到能够捕获对数组的访问的程度我可以方便地访问简单属性的属性。有没有办法在ctypes通过_fields_
变量创建的可索引对象上执行此操作?是否可以覆盖__setitem__
上的s.array
?可能有更好的方法来做这件事吗?
理想情况下,会发生这种情况:
>>> s = MyCStruct()
>>> s.attributes_updated
False
>>> s.array[2] = 456
>>> s.attributes_updated
True
编辑后续问题:
多维数组怎么样?
class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', (c_int*5)*2]
我错误地预期下面的答案,对于单维数组来说,它可以为任意嵌套的数组做出相同的工作。应该有一种方法来递归生成代理对象,为具有多个维度的数组做同样的事情,是吗?语法让我感到厌烦。
答案 0 :(得分:1)
我认为一个很好的解决方案是返回代理对象而不是数组,然后可以处理对数组的访问。可能是这样的:
from ctypes import *
class ArrayProxy(object):
def __init__(self, array, struct):
self.array = array
self.struct = struct
def __setitem__(self, i, val):
self.array[i] = val
self.struct.attributes_updated = True
def __getitem__(self, i):
item = self.array[i]
if issubclass(type(item), Array):
# handle multidimensional arrays
return ArrayProxy(item, self.struct)
return item
class Comm(Structure):
def __init__(self):
self.attributes_updated = False
def __setattr__(self, name, value):
super(Comm, self).__setattr__('attributes_updated', True)
super(Comm, self).__setattr__(name, value)
def __getattribute__(self, name):
attr = super(Comm, self).__getattribute__(name)
if issubclass(type(attr), Array):
return ArrayProxy(attr, self)
return attr
class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', c_int*5),
('multiarray', c_int*2*1),]
def __init__(self):
Comm.__init__(self)
s = MyCStruct()
print s.array
# <__main__.ArrayProxy object at 0x1b1f3d0>
print s.attributes_updated
# False
s.array[0] = 1
print s.attributes_updated
# True
s2 = MyCStruct()
s2.multiarray[0][0] = 1
print s2.attributes_updated
# True