首页 > 解决方案 > 如何使用 SWIG 包装 HWND 和 HINSTANCE 类型?

问题描述

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

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

我在使用这个函数时遇到了问题,因为我没有PythonHINSTANCEHWNDPython 的类型。根据此函数的文档,这些值可以是 null、0 或基本上任何值(目前是一个未使用的功能),所以我试图弄清楚如何使用typemap这些整数来生成这些整数,这样我就可以传入 0。从我的.i文件:

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

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

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

根据我的阅读,我相信HINSTANCEandHWND是“结构”,因此我需要做一些事情才能将结构“转换”为整数,但不幸的是,这一切都超出了我的想象。我主要是一个自学成才的 Python 程序员,处理 C/C++ 数据类型相当混乱。

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

标签: pythonc++ctypesswig

解决方案


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

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

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

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

但是,无论 HWND 和 HINSTANCE 是指向不透明类的指针还是指向 的指针void,即使您可以在 32b Windows 上强制转换它们,但在 64b 中从longto void*(或“ 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 {
    $1 = (HINSTANCE)PyLong_AsVoidPtr($input);
}

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

当然,如果两者HWNDHINSTANCE确实都void*符合 Microsoft 文档页面,那么该演员阵容将是无效的。


推荐阅读