简体   繁体   中英

How to fix “swig/python detected a memory leak of type 'HWND *', no destructor found”?

Consider this 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"

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"],
)

In order to run it, make sure you adjust properly the library_dirs variable and then just type:

python setup.py build_ext --inplace

If the extension has been generated succesfully then you just run python test.py and you should see an output similar to this:

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

I know you can use swig -nodefaultdtor to not generate implicit default destructors, I've tried and that didn't make any difference.

For the sake of completeness, here's roughly how the HWND typedefs would look like:

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

QUESTION: What's the proper way in swig to prevent that memory leak of HWND?

SWIG wasn't provided a definition of HWND and treats it as an opaque class. Note that %include "mcve.h" does NOT recurse into #include <windows.h> and only processes code directly in mcve.h , so SWIG has no definition at all.

There are a couple of solutions:

  • Give SWIG a definition that it understands. SWIG has a default for void* , and would correctly handle the following definition:
%module mcve

%{
#include "mcve.h"
%}

typedef void* HWND;

%include "mcve.h"
  • You can make custom typemaps instructing Python how to convert an HWND to and from a Python object. Unlike the previous solution, which returns a SWIG-wrapped void* object, this solution treats handles as integers:
%module mcve

%{
#include "mcve.h"
%}

%typemap(in) HWND %{
    $1 = PyLong_AsVoidPtr($input);
%}

%typemap(out) HWND %{
    $result = PyLong_FromVoidPtr($1);
%}

%include "mcve.h"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM