Just experimenting, but I was wondering if it's possible to make this code work (as in compile):
void main() {
int number = 5;
DWORD(*dontThreadOnMe)(PVOID) = [](PVOID data) {
int value = *(int*) data;
cout << value << endl;
cout << "This callback executed successsfully" << endl;
};
CreateThread(NULL, NULL, dontThreadOnMe, &number, NULL, NULL);
cin.get();
}
I have this nagging suspicion that because the standard signature for a LPTHREAD_START_ROUTINE
callback is DWORD WINAPI Callback(PVOID)
I won't be able to get this to compile without the added (but grammatically illegal) WINAPI
tag. Speaking of which, what exactly are the WINAPI
and CALLBACK
(for say WndProc
) attributes? I've never really understood why in certain circumstances you could have multiple attributes on a function.
Actually this is possible with Visual C++ 2012 and above; to quote from Microsoft's list of C++ feature support:
Additionally in Visual C++ in Visual Studio 2012, stateless lambdas are convertible to function pointers. ... we've made stateless lambdas convertible to function pointers that have arbitrary calling conventions. This is important when you are using APIs that expect things like __stdcall function pointers
So in Visual C++ 2012 you can do something like:
unsigned int id;
HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex(0, 0,
[](void* pData) -> unsigned int {
// I'm a thread!
return 0;
}, pThreadData, 0, &id));
This means you can also use lambdas with other API functions that expect callback functions (things like EnumWindows()
and CreateDialogParam()
, for example).
You can make things a little less wordy using auto :)
auto dontThreadOnMe = [](LPVOID data) -> DWORD {
int value = *(int*)data;
std::cout << value << std::endl;
std::cout << "This callback executed successsfully" << std::endl;
return 0; //don't forget your return code!
};
int number = 42;
auto thread = CreateThread(nullptr, 0, dontThreadOnMe, &number, 0, nullptr);
Or, for the copy paste addicts who find this answer later on ;), this is all you need:
auto work = [](LPVOID data) -> DWORD { return 0; };
int thread_param = 42;
auto thread = CreateThread(nullptr, 0, work, &thread_param, 0, nullptr);
At least in current* versions of Mingw64 you can specify the calling convention of a lambda function, as in []() WINAPI {}
:
CreateThread(
nullptr, // lpThreadAttributes
0, // dwStackSize
[](void *param) WINAPI -> DWORD { // lpStartAddress
(void) param;
return 0;
},
nullptr, // lpParameter
0, // dwCreationFlags
nullptr // lpThreadId
);
*) Tested with i686-w64-mingw32-g++-win32 (GCC) 6.3.0 20170516. Earlier version may work, too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With