単純なオブジェクトへのネストされたポインタはうまくいくようです。ドキュメンテーションはctypesが "元のオブジェクトの復帰"をサポートしていないことを明示していますが、ポインターがPythonリファレンスを保持してターゲットオブジェクトをキープアライブすることを意味しています。
>>> from ctypes import *
>>> x = c_int(7)
>>> triple_ptr = pointer(pointer(pointer(x)))
>>> triple_ptr.contents.contents.contents.value == x.value
True
>>> triple_ptr.contents.contents.contents is x
False
>>> triple_ptr._objects['1']._objects['1']._objects['1'] is x # CPython 3.5
True
ポインタ機能(create_string_buffer
がc_char * size
に関するどのような)POINTERテンプレートコンストラクタに異なっていないように見えます。
>>> type(pointer(x)) is type(POINTER(c_int)(x))
True
voidへのキャストも参照を保持しているようです(ただし、元のポインタを変更する理由はわかりません)。
>>> ptr = pointer(x)
>>> ptr._objects
{'1': c_int(7)}
>>> pvoid = cast(p, c_void_p)
>>> pvoid._objects is ptr._objects
True
>>> pvoid._objects
{139665053613048: <__main__.LP_c_int object at 0x7f064de87bf8>, '1': c_int(7)}
>>> pvoid._objects['1'] is x
True
オブジェクトをメモリバッファ(またはそのアドレス)から直接作成することは、いっそう厄介です。
>>> v = c_void_p.from_buffer(triple_ptr)
>>> v2 = c_void_p.from_buffer_copy(triple_ptr)
>>> type(v._objects)
<class 'memoryview'>
>>> POINTER(POINTER(POINTER(c_int))).from_buffer(v)[0][0][0] == x.value
True
>>> p3 = POINTER(POINTER(POINTER(C_int))).from_address(addressof(triple_ptr))
>>> v2._objects is None is p3._objects is p3._b_base_
True
ちなみに、byrefはおそらくそれが参照するメモリを保持しています。
>>> byref(x)._obj is x
True
私は、プログラムが終了したときに限りそうだと思います。 – YOU