Reputation:
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?
Upvotes: 2
Views: 23920
Reputation: 41137
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 ctypes as cts
import sys
def int_factory(fields):
return type("Int", (cts.Structure,), {"_fields_": fields})
def user(values=[1, 2]):
int_fields = (("first_16", cts.c_int, 16), ("second_16", cts.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(*argv):
int0 = user()
print_int_obj_data(int0)
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q030799760]> "e:\Work\Dev\VEnvs\py_pc064_02.07.18_test0\Scripts\python.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.
Might also check [SO]: Dynamically defining/updating ctypes structure in Python (@CristiFati's answer).
Upvotes: 5