You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:55:21