2

I have created subtructure and structure in ctypes as below where I am defining a array of substructure inside structure with some predefined size. (As per requirement SIZE may be set to 0 initially and can varies based on user input).

from ctypes import *

class MySubStructure(Structure):
    _fields_ = [
        ("sub_field1", c_uint32),
        ("sub_field2", c_uint32)
    ]


class MyStructure(Structure):
    SIZE = 2
    _fields_ = [
        ("field1", c_uint32),
        ("field2", c_uint32),
        ("sub_structure_field", ARRAY(SubStructure, SIZE)),
    ]

My goal is to modify this substructure based on user input.

For achieving the same I have tried below options but had no success:

  1. Defining a __init__ method and updating _fields_ while initializing the instance

  2. Updating _fields_ after initializing instance

For both of those options I tried to appending sub_structure_field, updating only size value by accessing through index.

Finally I just want a workaround so that I can use array of structure inside another structure either initializing at runtime or modifying at runtime.

1 Answer 1

2

Mentioning [Python.Docs]: ctypes - A foreign function library for Python.

The array size must be known at the moment _fields_ is defined.
You could have a factory function which defines the class and returns it.

code00.py:

#!/usr/bin/env python

import ctypes as cts
import sys


class SubStructure(cts.Structure):
    _fields_ = (
        ("sub_field1", cts.c_uint32),
        ("sub_field2", cts.c_uint32),
    )


def structure_factory(size):
    class DynamicStructure(cts.Structure):
        _fields_ = (
            ("field1", cts.c_uint32),
            ("field2", cts.c_uint32),
            ("sub_structure_field", SubStructure * size),  # Equivalent to: cts.ARRAY(SubStructure, size)
        )

    return DynamicStructure


def main(*argv):
    Struct2 = structure_factory(2)  # DynamicStructure type NOT instance
    Struct5 = structure_factory(5)  # -- // --
    print(Struct2.sub_structure_field)
    print(Struct5.sub_structure_field)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(item.strip() for item 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\q057417435]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 064bit on win32

<Field type=SubStructure_Array_2, ofs=8, size=16>
<Field type=SubStructure_Array_5, ofs=8, size=40>

Done.

You could also take a look at [SO]: Setting _fields_ dynamically in ctypes.Structure (@CristiFati's answer).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.