2011-08-18 50 views
3

這裏是輸出:聊齋志異「無效的轉換,從<type>到<type>」錯誤

g++ -DDEBUG -DUNITTEST -IC:/Users/Steven/Dropbox/Programming/entropy_p5_makefile/cpp/game/../include/ -O0 -g3 -Wall -c -fmessage-length=0 -o Input.o ..\Input.cpp 
..\Input.cpp: In function 'void mousehookCustomRoutine(E_thread*, void*)': 
..\Input.cpp:78:93: error: invalid conversion from 'LRESULT (*)(int, WPARAM, LPARAM)' to 'LRESULT (*)(int, WPARAM, LPARAM)' 
..\Input.cpp:78:93: error: initializing argument 2 of 'void* SetWindowsHookExA(int, LRESULT (*)(int, WPARAM, LPARAM), HINSTANCE__*, DWORD)' 
Build error occurred, build is stopped 

這是代碼:

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) { 
    //... 
} 

void mousehookCustomRoutine(E_thread *me, void *arg = (void *)&MouseHookProc) { 
    // arg is the ptr to LL Mouse Routine 

    me->sendMessage(0x14,me,(void*)GetCurrentThreadId()); 
    // send message to self in order for my parent to know how to identify me via threadID 
    HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, (LRESULT (*)(int,WPARAM,LPARAM))arg,NULL, 0); // I am line 78 
    if (mousehook == NULL) printf("Mousehook error %lu\n",GetLastError()); 
    //... 
} 

這是沒有意義的,因爲我鑄造的確切類型,它期望收到,沒有任何限定詞或任何不同的東西。這裏可能會發生什麼?

回答

2

首先,不要將函數指針轉換爲void *。調用另一種類型的函數後再調用一種類型的函數是不安全的,因此很少有必要使它們成爲void *

其次,可能你會看到調用約定的差異。掛鉤參數的類型正確說明,(LRESULT (CALLBACK *) (int, WPARAM, LPARAM))或簡單地HOOKPROC。函數的原型應該看起來像LRESULT CALLBACK MouseHookProc(int, WPARAM, LPARAM)。 gcc很可能不會打印調用約定說明符,但在檢查類型等價性時會檢查它。像這樣的微妙問題是另一個不投射函數指針的原因 - 如果您使用了(HOOKPROC)強制轉換,您將不會有編譯時錯誤,但可能在運行時崩潰...... but only on certain versions of windows

+0

好的。我將着眼於試圖通過指定調用約定來實現它。感謝您對鑄造'void *'的警告。問題在於'mousehookCustomRoutine'函數被髮送給線程生成器,即它是定義線程的函數。因爲這個函數需要有一個可以傳遞給線程啓動器的類型。我可以分配一個持有函數指針的結構而不需要強制轉換它,並通過'void * arg'將一個指針傳遞給那個函數,但是我認爲指針的大小都一樣大,爲什麼不用'void *'來保存值? –

+0

@Steven,啊,線程參數可能是個例外。但是,你必須非常小心,你的類型是你所期望的。我會將線程創建包裝在一個函數中,該函數會在轉換爲'void *'之前檢查傳入回調的類型。 – bdonlan

+0

好吧,啓動線程的函數將被定義爲需要與其參數完全相同的函數指針類型,並且它繼續創建一個線程通過傳遞它。在我看來,如果我發送這個函數錯誤的類型(包括調用約定),它會抱怨,因爲這個問題的錯誤彈出完全相同的原因。 –

3

編譯器正在從錯誤消息中省略調用約定 - SetWindowsHookEx想要一個LRESULT (__stdcall *)(int,WPARAM,LPARAM),但是您將它傳遞給LRESULT (__cdecl *)(int,WPARAM,LPARAM)

相關問題