ctypes.Structure 运行时修改 _fields_
可以在导入后修改ctypes.Structure
的_fields_
定义吗?
类似于:
from ctypes import *
class A_STRUCT(Structure):
_fields_ = [("one",c_int)]
A_STRUCT._fields_.append(("two",c_int))
x = A_STRUCT()
print x.one
print x.two
这显然会失败,错误信息是:
0
Traceback (most recent call last):
File "structEnumTest.py", line 10, in <module>
print x.two
AttributeError: 'A_STRUCT' object has no attribute 'two'
编辑
我的使用场景是我有两个版本的A_STRUCT
。版本2和版本1相同,只是在版本1的末尾添加了一些字段。我希望能避免像这样的情况。我在运行时才知道需要哪个版本的结构体。
class A_STRUCT_V1(Structure):
_fields_ = [("one",c_int)]
class A_STRUCT_V2(Structure):
_fields_ = [("one",c_int),("two",c_int)]
2 个回答
3
我知道这个问题很老套,但你可以通过子类化轻松解决你的问题:
class A_STRUCT_V1(Structure):
_fields_ = [("one",c_int)]
class A_STRUCT_V2(A_STRUCT_V1):
_fields_ = [("two",c_int)]
对于类型为 A_STRUCT_V2 的对象,'two' 会紧接着 'one' 存储在内存中。
如果子类的 字段 名称和父类的 字段 成员重复,父类的 字段 并不会被替换,它仍然占用相同的内存(虽然用类似 child.two 的语句无法访问到父类的字段),而第二个成员会放在它之后。
5
不,正如你在这个链接中看到的,PyCStructType_Type
是一个自定义的元类(你可以在我刚提到的C代码的327行及之后找到)。而Structure
(4136行及之后)使用了这个元类(在5532行及之后有说明)。当你使用class
语句时,特别是当自定义元类的__new__
被调用来创建一个继承自Structure
的新类时,所有可以通过C访问的字段才会被真正定义(而且ctypes
很贴心地让其他“偷偷引入”的字段在Python中不可访问,以避免意外发生;-)。
你到底想解决什么问题呢?是那种在你了解到额外字段时,无法通过从头开始重建A_STRUCT
来解决的问题吗?比如说,如果你的问题是已经存在一些“旧版”的A_STRUCT
实例,那么显然这些实例并没有你刚刚了解到的新字段。所以,即使通过某种不可思议的方式修改这个类也是没什么用的;-)。