ctypes.Structure Изменить _fields_ во время выполнения - PullRequest
2 голосов
/ 10 августа 2010

Можно ли изменить определение _fields_ для ctypes.Structure после его импорта?

Что-то вроде:

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 такая же, с дополнительными полями, добавленными в конец первой версии.Я надеялся избежать чего-то подобного.Я не знаю, какая версия структуры нужна до времени выполнения.

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

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

Ответы [ 2 ]

5 голосов
/ 10 августа 2010

Нет, как вы можете видеть в source , PyCStructType_Type - это пользовательский метакласс (см. Строки 327ff в только что указанном коде C), а Structure (строки 4136ff) использует его (как выставлено в 5532ff).Оператор class (в частности, когда вызывается __new__ из пользовательского метакласса для создания нового класса, который наследуется от Structure) - это когда все поля, доступные для C, фактически определены (и было бы неплохо сделать ctypesдругие «контрабандные» поля, недоступные также из Python, чтобы избежать несчастных случаев; -).

Какую именно проблему вы пытаетесь решить, которую вы не могли решить, восстанавливая A_STRUCT с нуля нараз вы узнали о дополнительных полях?Например, если ваша проблема в том, что уже есть экземпляры «старого» * ​​1012 *, то, очевидно, эти экземпляры не имеют новых полей, о которых вы только что узнали, поэтому модифицируйте класс, даже если черезкакое-то невероятное искривление, это было возможно, не было бы так полезно; -).

2 голосов
/ 26 октября 2016

Я знаю, что это очень старый вопрос, но вы можете легко решить свою проблему, создав подклассы:

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

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

'two' будет сразу следовать 'one' в памяти для объектов типа A_STRUCT_V2

Если подклассы fields name дублируют его родительский класс fields member, родительский не заменяется , он по-прежнему занимает ту же память (хотя недоступен с помощьюоператор, подобный child.two, и второй член ставится после него.

...