2013-08-21 51 views
5

只是嘗試,但我想知道如果有可能使這個代碼的工作(如編譯):使用的CreateThread與拉姆達

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)如果沒有添加(但語​​法上非法)的標記,我將無法獲得此代碼。說到這個,WINAPICALLBACK(比如說WndProc)屬性究竟是什麼?我從來沒有真正理解爲什麼在某些情況下,你可以在一個函數上有多個屬性。

+0

'main'需要'int'作爲返回類型。你還需要一個'__stdcall' lambda,這是不可能的。不過,您可以將其包裝爲lambda(或其他),或者只使用''。 – chris

+7

既然你明明在使用C++ 11,爲什麼不直接使用'std :: thread',它是可移植的,並且和lambda表達式很好地集成在一起,而不是特定於平臺的'CreateThread'呢? – syam

+0

我只是剛開始學習。但我會研究這一點。謝謝! – sircodesalot

回答

11

實際上,這對於Visual C++ 2012及更高版本是可行的;從Microsoft's list of C++ feature support引用:

此外在Visual Studio 2012的Visual C++,無國籍的lambda表達式 可以轉化爲函數指針。 ...我們已將無狀態的 lambda轉換爲函數指針,它們可以任意調用 約定。這一點很重要,當你使用的是期望像__stdcall函數指針 事情的API

所以在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)); 

這意味着你還可以使用lambda表達式與其他API需要回調函數的函數(例如EnumWindows()CreateDialogParam()等)。

+2

啊哈!我長期以來一直想知道,考慮到x86 ABI需要'__stdcall'作爲其大部分線程入口點(x64並不重要),這將如何工作。感謝您指出這一點,** + 1 ** –

2

可以使事情少羅嗦使用自動:)

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); 
+0

編譯器說我不能將lambda放入LPTHREAD_START_ROUTINE – J3STER

0

至少在當前*版本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進行測試。早期版本也可以。