如何使用 SWIG 包装 HWND 和 HINSTANCE 类型?

How do I wrap HWND and HINSTANCE types with SWIG?

我正在用 SWIG 包装第三方提供的 Windows DLL,以便在 Python 中使用。我已经能够成功编译我的 SWIG 模块并将其导入 Python,但我 运行 遇到一个函数(来自 .h 头文件)的问题:

_APPFN ServerID _CALLCONV OpenServer(HINSTANCE hAppInst, HWND hWnd);

我 运行 遇到了使用此函数的问题,因为我在 Python 中没有 HINSTANCEHWND 的类型。根据此函数的文档,这些值可以是 null、0 或基本上任何东西(当前未使用的功能),所以我试图弄清楚如何使用 typemap 来生成这些整数,这样我就可以通过在 0 秒。来自我的 .i 文件:

/* handle HINSTANCE */
%typemap(in) HINSTANCE {
     = PyInt_AsLong($input);
}

/* handle hwnds */
%typemap(in) HWND {
     = PyInt_AsLong($input);
}

当我尝试使用上述类型映射编译我的包装文件(我正在使用 Visual Studio)时,出现错误:cannot convert from 'long' to 'HINSTANCE'cannot convert from 'long' to 'HWND'.

根据我的阅读,我认为 HINSTANCEHWND 是 "structs",因此我需要做一些事情才能 "cast" 结构到整数,但不幸的是,这一切都超出了我的理解范围。我主要是一个自学成才的 Python 程序员,处理 C/C++ 数据类型相当混乱。

我希望有人可以看看我在做什么,并指导我如何更改类型映射。

根据 Microsoft 文档,这些类型是 void*s: https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types

尽管可以肯定,cppyy(通过 Clang 解析 Windows headers)将它们解析为指向不透明类型的指针(即向前声明,但未定义):

$ python
>>> import cppyy
>>> print(cppyy.gbl.HWND)
<cppyy.TypedefPointerToClass object at 0x00000245E8839558>
>>>

因此,如果您想确定的话,您可能需要查找 typedef。

但是,无论 HWND 和 HINSTANCE 是指向不透明 类 的指针还是指向 void 的指针,即使您可以将它们投射到 32b Windows、64b 从 longvoid*(或“opaque*”)将不起作用,因为 long 值将被截断。因此,在您的类型图中使用 PyLong_AsVoidPtr 而不是 PyInt_AsLong。请参阅 Python C-API 文档: https://docs.python.org/3/c-api/long.html#c.PyLong_AsVoidPtr

如果类型是不透明的 类,您还需要显式转换,最终代码如下所示:

/* handle HINSTANCE */
%typemap(in) HINSTANCE {
     = (HINSTANCE)PyLong_AsVoidPtr($input);
}

/* handle hwnds */
%typemap(in) HWND {
     = (HWND)PyLong_AsVoidPtr($input);
}

当然,如果根据 Microsoft 文档页面 HWNDHINSTANCE 确实是 void*,那么该转换将是 no-op.