什么时候ctypes释放内存?

时间:2016-08-06 23:36:19

标签: python memory-management ctypes

在Python中我使用ctypes与C库交换数据,而调用接口涉及嵌套指向结构的指针。

如果内存是从C中分配的,那么python应该(深度)提取任何所需值的副本,然后明确要求C库释放内存。

如果内存是从Python中分配的,可能在相应的ctypes对象超出范围后很快就会释放内存。这如何用于指针?如果我从字符串缓冲区创建一个指针对象,那么我是否需要保留一个变量引用该范围内的原始缓冲区对象,以防止此指针悬空?或者指针对象本身是否会自动为我执行此操作(即使它不会返回原始对象)?我使用pointerPOINTERcastc_void_p还是from_address(addressof)会有什么不同吗?

1 个答案:

答案 0 :(得分:0)

对简单对象的嵌套指针似乎很好。文档明确表示ctypes不支持"原始对象返回",但暗示指针确实存储了python-reference以保持其目标对象(精确的机制可能是实现)特异性)。

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

看起来指针函数与POINTER模板构造函数没什么区别(就像create_string_bufferc_char * size的关系一样)。

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