Рассмотрим этот 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"],
)
Чтобы запустить его, убедитесь, что вы правильно настроили переменную 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 PVOID HANDLE;
typedef HANDLE HWND;
typedef void *PVOID;
ВОПРОС: Как в swig правильно предотвратить утечку памяти HWND?
FYI test.py
упоминается, но не предоставляется.
SWIG не предоставил определение HWND
и рассматривает его как непрозрачный класс. Обратите внимание, что %include "mcve.h"
НЕ рекурсивно переходит в #include <windows.h>
и обрабатывает код только непосредственно в mcve.h
, поэтому SWIG вообще не имеет определения.
Есть несколько решений:
void*
и правильно обработает следующее определение:%module mcve
%{
#include "mcve.h"
%}
typedef void* HWND;
%include "mcve.h"
%module mcve
%{
#include "mcve.h"
%}
%typemap(in) HWND %{
$1 = PyLong_AsVoidPtr($input);
%}
%typemap(out) HWND %{
$result = PyLong_FromVoidPtr($1);
%}
%include "mcve.h"
Связанный вопрос: https://stackoverflow.com/a/920988/3809375