'How to setattr in ctypes.pointer.contents?

I'm using a custom ctypes in my code, but I found that I can setattr nothing in ctypes.pointer.contents. See this code:

import ctypes

class Test(ctypes.Structure):
    _fields_ = (("value", ctypes.c_int), )

    def __init__(self,  *args, **kwargs):
        self.vars_len = 1
        super().__init__(*args, **kwargs)

t = Test(5)
pt = ctypes.pointer(t)
print(f"t.vars_len:{t.vars_len}")
print(hasattr(pt.contents, "vars_len"))
pt.contents.vars_len = "hello"
print(hasattr(pt.contents, "vars_len"))

output:

t.vars_len:1
False
False

Neither the definition at instantiation time nor the setattr take effect. So I wonder how to setattr in ctypes.pointer.contents? I want to realize a custom ctypes, which is a variable length point, has "vars_len" attr to discripe the length of data, but I don't want to modify the ctype's _fields_. Or is there another way?



Solution 1:[1]

You can't do this. Test wraps a memory structure. pt wraps a pointer to the memory structure itself, not the Test object. When you access pt.contents a new Test object is created and returned to wrap memory structure at that address each time it is accessed. It's not the original Test object where the attribute was stored.

Note the IDs of the objects are all different below:

import ctypes

class Test(ctypes.Structure):
    _fields_ = (("value", ctypes.c_int), )

    def __init__(self,  *args, **kwargs):
        self.vars_len = 1
        super().__init__(*args, **kwargs)

t = Test(5)
pt = ctypes.pointer(t)
print(id(t))
a = pt.contents
b = pt.contents
c = pt.contents
print(id(a))
print(id(b))
print(id(c))

Output:

2453287249216
2453287249472
2453275065920
2453287248448

The memory stucture would need to have the length in the data itself and referred to by _fields_.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mark Tolonen