Python调用Windows API时ctypes内存释放的三类场景确认
PySide2结合ctypes调用Windows API的内存泄漏疑问解答
我正在使用PySide2构建Python GUI,需通过ctypes调用Windows API。我有C++基础,熟悉内存分配/释放,但对Python调用C的内存管理存疑,特确认以下三类场景是否存在内存泄漏:
1. Windows/Qt管理的结构体指针
class NCCALCSIZE_PARAMS(Structure): _fields_ = [("rgrc", RECT * 3), ("lppos", POINTER(PWINDOWPOS))] LPNCCALCSIZE_PARAMS = POINTER(NCCALCSIZE_PARAMS) rect = cast(msg.lParam, LPNCCALCSIZE_PARAMS).contents.rgrc[0] rect.left += thickness
结论:无内存泄漏。NCCALCSIZE_PARAMS的内存由Windows/Qt完全管理,Python侧仅通过cast获取了指向该内存的视图,并未接管内存所有权。rect是原内存中rgrc[0]的本地拷贝(RECT属于值类型结构体),修改rect.left仅操作本地拷贝数据,原内存依然由Windows/Qt负责释放。等rect变量超出作用域后,Python会自动回收这个拷贝的内存。
2. 传递初始化的ctypes结构体引用
class MARGINS(ctypes.Structure): _fields_ = [("cxLeftWidth", c_int), ("cxRightWidth", c_int), ("cyTopHeight", c_int), ("cyBottomHeight", c_int) ] margins = MARGINS(1, 1, 1, 1) dwm.DwmExtendFrameIntoClientArea(msg.hWnd, ctypes.byref(margins))
结论:无内存泄漏。margins是Python侧创建的ctypes结构体实例,其内存由Python的垃圾回收机制管理。调用API时用ctypes.byref传递的是临时指针,函数调用完成后该临时指针自动失效,原margins结构体的生命周期由Python控制,当它被垃圾回收时,对应的内存会自动释放,无需手动干预。
3. 使用ctypes from_address()
def nativeEvent(self, event, message): msg = MSG.from_address(message.__int__()) return QtWidgets.QWidget.nativeEvent(self, event, message)
结论:无内存泄漏。MSG.from_address()仅在Python侧创建了对应内存地址的结构体视图,既没有复制内存,也没有接管内存所有权。原MSG结构体的内存由Windows/Qt负责分配和释放,Python侧的msg实例只是对该内存的映射,当msg超出作用域后,Python仅回收这个视图对象,不会触及底层的Windows内存,无需手动释放。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

