Search code examples
c++c++11winapilambdamingw

mingw: Invalid conversion from lambda to function pointer


Trying to supply a lambda as a function pointer to a Win32 API call fails when compiling using mingw 5.3.0, although it compiles fine when using MSVC (of Visual Studio 2013).

MCVE:

#include <Windows.h>

int main(int argc, char *argv[])
{
    bool parameterData;

    EnumWindows([](HWND windowHandle, LPARAM parameter) -> BOOL {
        return 1;
    }, reinterpret_cast<LPARAM>(&parameterData));
}

GCC throws the following error message, which I can't wrap my head around:

error: invalid user-defined conversion from 'main(int, char**)::<lambda(HWND, LPARAM)>' to 'WNDENUMPROC {aka int (__attribute__((__stdcall__)) *)(HWND__*, long int)}' [-fpermissive]
  }, reinterpret_cast<LPARAM>(&parameterData));
                                             ^
note: candidate is: main(int, char**)::<lambda(HWND, LPARAM)>::operator BOOL (*)(HWND, LPARAM)() const <near match>
  EnumWindows([](HWND windowHandle, LPARAM parameter) -> BOOL {
                                                         ^
note:   no known conversion from 'BOOL (*)(HWND, LPARAM) {aka int (*)(HWND__*, long int)}' to 'WNDENUMPROC {aka int (__attribute__((__stdcall__)) *)(HWND__*, long int)}'
In file included from C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/Windows.h:72:0,
                 from main.cpp:1:
note:   initializing argument 1 of 'WINBOOL EnumWindows(WNDENUMPROC, LPARAM)'
   WINUSERAPI WINBOOL WINAPI EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);

What is it exactly that GCC does not like? What needs to be changed in order to use the lambda as first parameter to EnumWindows?


Solution

  • EnumWindows expects a callback with the stdcall calling convention. GCC has no support for converting stateless lambdas into stdcall function pointers, and there's no way that I'm aware of to mark the lambda as such. MSVC, however, provides conversions to function pointers with a variety of calling conventions.

    Unfortunately, you're going to have to use a separate function or use MSVC:

    BOOL CALLBACK callback(HWND windowHandle, LPARAM parameter) { ... }
    ...
    EnumWindows(callback, reinterpret_cast<LPARAM>(&parameterData));