简体   繁体   中英

How do I wrap HWND and HINSTANCE types with SWIG?

I'm wrapping a third-party provided Windows DLL with SWIG for use in Python. I have been able to successfully compile my SWIG module and import it into Python, but I'm running into issues with one function (from the .h header file):

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

I'm running into issues using this function, because I don't have types for HINSTANCE or HWND in Python. Per the documentation for this function, these values can be null, 0, or basically anything (currently an unused feature), so I'm trying to figure out how to use typemap to make these integers so I can just pass in 0s. From my .i file:

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

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

When I try to compile my wrapper file (I'm using Visual Studio) with the above typemaps, I get errors: cannot convert from 'long' to 'HINSTANCE' and cannot convert from 'long' to 'HWND' .

Based on my reading, I believe that HINSTANCE and HWND are "structs", and so I need to do something in order to "cast" the struct to an integer, but unfortunately, this is all really above my head. I'm mostly a self-taught Python programmer, and dealing with C/C++ data typing is rather confusing.

I'm hoping that someone can look at what I'm doing, and guide me on how I need to change my typemapping.

These types are void* s per the Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types

Although to be sure, cppyy (through Clang parsing the Windows headers) resolves them as pointers to opaque types (ie forward declared, but not defined):

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

so you may want to look up the typedefs if you want to know for sure.

However, regardless whether HWND and HINSTANCE are pointers to opaque classes or pointers to void , even as you could cast them on 32b Windows, on 64b casting from long to void* (or " opaque* ") won't work because the long value will have been truncated. So, use PyLong_AsVoidPtr instead of PyInt_AsLong in your typemap. See the Python C-API documentation: https://docs.python.org/3/c-api/long.html#c.PyLong_AsVoidPtr

If the types are of opaque classes, you will also need the explicit cast, and the final code would look like:

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

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

Of course, if both HWND and HINSTANCE are indeed void* as per that Microsoft documentation page, then that cast will be a no-op.

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