如何修复"swig/python detected a memory leak of type 'HWND *', no destructor found"?



考虑这个mcve:

mcve.h

#pragma once
#include <windows.h>
class Windows {
public:
static HWND GetActiveWindow();
static HWND GetForegroundWindow();
};

mcve.cpp

#include "mcve.h"
HWND Windows::GetActiveWindow() {
return ::GetActiveWindow();
}
HWND Windows::GetForegroundWindow() {
return ::GetForegroundWindow();
}

mcve.i

%module mcve
%include <std_string.i>
%include <std_vector.i>
%include <typemaps.i>
%include <windows.i>
%include <cpointer.i>
%include <carrays.i>
%{
#include "mcve.h"
%}

%include "mcve.h"

设置.py

from distutils.core import Extension
from distutils.core import setup
setup(
name="mcve",
ext_modules=[
Extension(
"_mcve",
sources=["mcve.i", "mcve.cpp", "mcve_wrap.cpp"],
swig_opts=["-c++", "-python"],
include_dirs=["."],
library_dirs=[
"D:/software/vcpkg/installed/x86-windows/lib"
],
libraries=["user32"]
)
],
py_modules=["mcve"],
)

为了运行它,请确保正确调整library_dirs变量,然后只需键入:

python setup.py build_ext --inplace

如果扩展已经成功生成,那么您只需运行python test.py,就会看到类似于以下内容的输出:

>python test.py
swig/python detected a memory leak of type 'HWND *', no destructor found.
swig/python detected a memory leak of type 'HWND *', no destructor found.

我知道您可以使用swig-nodefaultdtor来不生成隐式默认析构函数,我已经尝试过了,但没有任何区别。

为了完整起见,以下是HWND typedef的大致样子:

typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef void *PVOID;

问题:swig中防止HWND内存泄漏的正确方法是什么?

SWIG没有提供HWND的定义,并将其视为不透明类。注意,%include "mcve.h"不会递归到#include <windows.h>中,只直接在mcve.h中处理代码,因此SWIG根本没有定义。

有几个解决方案:

  • 给SWIG一个它能理解的定义。SWIG具有void*的默认值,可以正确处理以下定义:
%module mcve
%{
#include "mcve.h"
%}
typedef void* HWND;
%include "mcve.h"
  • 您可以制作自定义类型映射,指导Python如何将HWND转换为Python对象和从Python对象转换HWND。与上一个返回SWIG包装的void*对象的解决方案不同,此解决方案将句柄视为整数:
%module mcve
%{
#include "mcve.h"
%}
%typemap(in) HWND %{
$1 = PyLong_AsVoidPtr($input);
%}
%typemap(out) HWND %{
$result = PyLong_FromVoidPtr($1);
%}
%include "mcve.h"

最新更新