如何修复 "swig/python detected a memory leak of type 'HWND *', no destructor found"?
How to fix "swig/python detected a memory leak of type 'HWND *', no destructor found"?
考虑这个问题:
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"
setup.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
的定义并将其视为不透明的 class。请注意,%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 对象相互转换。与之前的解决方案不同,后者 returns 一个 SWIG 包装的 void* 对象,此解决方案将句柄视为整数:
%module mcve
%{
#include "mcve.h"
%}
%typemap(in) HWND %{
= PyLong_AsVoidPtr($input);
%}
%typemap(out) HWND %{
$result = PyLong_FromVoidPtr();
%}
%include "mcve.h"
考虑这个问题:
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"
setup.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
的定义并将其视为不透明的 class。请注意,%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 对象相互转换。与之前的解决方案不同,后者 returns 一个 SWIG 包装的 void* 对象,此解决方案将句柄视为整数:
%module mcve
%{
#include "mcve.h"
%}
%typemap(in) HWND %{
= PyLong_AsVoidPtr($input);
%}
%typemap(out) HWND %{
$result = PyLong_FromVoidPtr();
%}
%include "mcve.h"