开发者

ctypes.Structure Modify _fields_ at Run Time

开发者 https://www.devze.com 2023-01-11 04:02 出处:网络
Is it possible to modify the _fields_ definition of the ctypes.Structure after it\'s been imported? Something like:

Is it possible to modify the _fields_ definition of the ctypes.Structure after it's been imported?

Something like:

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

Not surprisingly this fails with:

0
Traceback (most recent call last):
  File "structEnumTest.py", line 10, in <module>
    print x.two
AttributeError: 'A_STRUCT' object has no attribute 'two'

EDITS

My use case is that I have two version of A_STRUCT. Version 2 is the same with addit开发者_JS百科ional fields appended to the end of version one. I was hoping to avoid having something like this. I do not know which version of the struct is needed until run-time.

class A_STRUCT_V1(Structure):
     _fields_ = [("one",c_int)]

class A_STRUCT_V2(Structure):
     _fields_ = [("one",c_int),("two",c_int)]


No, as you can see in the sources, PyCStructType_Type is a custom metaclass (see lines 327ff in the C code I just pointed to) and Structure (lines 4136ff) uses it (as exposed in 5532ff). The class statement (specifically when the __new__ from the custom metaclass gets called to make the new class which inherits from Structure) is when all C-accessible fields are actually defined (and it's nice of ctypes to make other "smuggled in" fields inaccessible from Python as well to avoid accidents;-).

What problem, exactly, are you trying to solve, that you couldn't solve by rebuilding A_STRUCT from scratch at the time you learn about the extra fields? For example, if your issue is that there are instances of the "old" A_STRUCT already around, well, obviously, those instances don't have the new fields you've just learned about, so modifying the class, even if through some incredible contortion it was feasible, wouldn't be all that useful;-).


I know this is a very old question, but you can solve your problem easily by subclassing:

class A_STRUCT_V1(Structure):
     _fields_ = [("one",c_int)]

class A_STRUCT_V2(A_STRUCT_V1):
     _fields_ = [("two",c_int)]

'two' will immediately follow 'one' in memory for objects of type A_STRUCT_V2

If the subclasses fields name duplicates its parent class fields member, the parent's is not replaced, it still takes the same memory (though is inaccessible with a statement like child.two, and the second member is placed after it.

0

精彩评论

暂无评论...
验证码 换一张
取 消