只是试验,但我想知道是否可以使这段代码工作(如在编译中):
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();
}
我有这种唠叨的怀疑,因为LPTHREAD_START_ROUTINE
回调的标准签名是DWORD WINAPI Callback(PVOID)
我将无法在没有添加(但语法上非法){{1}的情况下进行编译} 标签。说到这些,WINAPI
和WINAPI
(对于说CALLBACK
)属性究竟是什么?我从来没有真正理解为什么在某些情况下你可以在一个函数上有多个属性。
答案 0 :(得分:15)
实际上,使用Visual C ++ 2012及更高版本可以实现这一点;引用Microsoft's list of C++ feature support:
此外,在Visual Studio 2012中的Visual C ++中,无状态lambda 可转换为函数指针。 ......我们已经成为无国籍人 lambdas可转换为具有任意调用的函数指针 约定。当您使用期望的API时,这很重要 像__stdcall函数指针
之类的东西
因此,在Visual C ++ 2012中,您可以执行以下操作:
unsigned int id;
HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex(0, 0,
[](void* pData) -> unsigned int {
// I'm a thread!
return 0;
}, pThreadData, 0, &id));
这意味着您还可以将lambdas与其他期望回调函数的API函数一起使用(例如EnumWindows()
和CreateDialogParam()
)。
答案 1 :(得分:3)
你可以使用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);
或者,对于稍后会发现此答案的复制粘贴上瘾者;),这就是您所需要的:
auto work = [](LPVOID data) -> DWORD { return 0; };
int thread_param = 42;
auto thread = CreateThread(nullptr, 0, work, &thread_param, 0, nullptr);
答案 2 :(得分:1)
至少在Mingw64的当前 * 版本中,您可以指定lambda函数的调用约定,如[]() WINAPI {}
中所示:
CreateThread(
nullptr, // lpThreadAttributes
0, // dwStackSize
[](void *param) WINAPI -> DWORD { // lpStartAddress
(void) param;
return 0;
},
nullptr, // lpParameter
0, // dwCreationFlags
nullptr // lpThreadId
);
*)使用i686-w64-mingw32-g ++ - win32(GCC)6.3.0 20170516进行测试。早期版本也可以使用。