Python 在 ctypes.Structure 中动态设置 _fields_

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30799760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:59:43  来源:igfitidea点击:

Setting _fields_ dynamically in ctypes.Structure

pythonctypes

提问by

Reading the documentation here, I see that you can use ctypes.Structure as follows :-

阅读此处的文档,我看到您可以按如下方式使用 ctypes.Structure :-

>>> class Int(Structure):
...     _fields_ = [("first_16", c_int, 16),
...                 ("second_16", c_int, 16)]
...
>>> print Int

Would it be possible for me to create such a class by using a list that I decide upon dynamically? For eg, something along the lines of :-

我是否可以通过使用我动态决定的列表来创建这样的类?例如,类似的东西:-

def int_factory(fields):
    int_class = get_int_class(fields) # This returns a class object with _fields_ set to fields
    return int_class

def user(values=[1,2]):
    int_class = int_factory(int_fields)
    i = int_class(values[0], values[1])

Would it be possible to do this?

有可能做到这一点吗?

采纳答案by CristiFati

In the example below:

在下面的例子中:

  • int_factorygenerates the Intclass
  • userreturns an Intinstance with first_16set to 1 and second_16set to 2
  • int_factory生成Int
  • 用户返回一个int实例,其中first_16设置为 1,second_16设置为 2

code.py:

代码.py

#!/usr/bin/env python3

import sys
from ctypes import Structure, \
    c_int


def int_factory(fields):
    return type("Int", (Structure,), {"_fields_": fields})


def user(values=[1, 2]):
    int_fields = (("first_16", c_int, 16), ("second_16", c_int, 16))  # This is just an example to illustrate your class definition. int_fields can be generated dynamically.
    int_class = int_factory(int_fields)
    int_obj = int_class(*values)
    return int_obj


def print_int_obj_data(int_obj):
    print("Type: {:}\n_fields_: {:}".format(int_obj.__class__.__name__, int_obj._fields_))
    for field in int_obj._fields_:
        print("    {:}: {:}".format(field[0], getattr(int_obj, field[0])))


def main():
    int0 = user()
    print_int_obj_data(int0)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Output:

输出

e:\Work\Dev\StackOverflow\q030799760>"e:\Work\Dev\VEnvs\py27x64_test\Scripts\python.exe" code.py
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32

Type: Int
_fields_: (('first_16', <class 'ctypes.c_long'>, 16), ('second_16', <class 'ctypes.c_long'>, 16))
    first_16: 1
    second_16: 2
e:\Work\Dev\StackOverflow\q030799760>"e:\Work\Dev\VEnvs\py27x64_test\Scripts\python.exe" code.py
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32

Type: Int
_fields_: (('first_16', <class 'ctypes.c_long'>, 16), ('second_16', <class 'ctypes.c_long'>, 16))
    first_16: 1
    second_16: 2