Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
676 views
in Technique[技术] by (71.8m points)

python - Setting _fields_ dynamically in ctypes.Structure

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

>>> 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In the example below:

  • int_factory generates the Int class
  • user returns an Int instance with first_16 set to 1 and second_16 set to 2

code00.py:

#!/usr/bin/env python

import sys
import ctypes as ct


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


def user(values=[1, 2]):
    int_fields = (("first_16", ct.c_int, 16), ("second_16", ct.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: {:}
_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(*argv):
    int0 = user()
    print_int_obj_data(int0)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}
".format(" ".join(elem.strip() for elem in sys.version.split("
")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("
Done.")
    sys.exit(rc)

Output:

[cfati@CFATI-5510-0:e:WorkDevStackOverflowq030799760]> "e:WorkDevVEnvspy_pc064_02.07.18_test0Scriptspython.exe" code00.py
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] 64bit 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

Done.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...