通过GetProcAddress函数动态调用dll中地函数,是否必须通过extern C声明导出函数?(转)...
生活随笔
收集整理的這篇文章主要介紹了
通过GetProcAddress函数动态调用dll中地函数,是否必须通过extern C声明导出函数?(转)...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
通過GetProcAddress函數動態調用dll中的函數,是否必須通過extern "C"聲明導出函數? [已結貼,結貼人:darongtou]
?
如題,網上搜了N多資料,一直找不到確定的答案,目前我的答案是“是”。?晚上因為一個程序,好好研究了一下。?很多資料上都只是說明“如果沒有 extern "C" 修飾,輸出函數僅僅能從 C++ 代碼中調用。”?卻并沒有明確這個調用是通過顯式調用還是隱式調用,我也一直沒有看到過有代碼是通過顯示調用沒有 extern "C" 修飾的導出函數。?MSDN上也只是說?The ? spelling ? and ? case ? of ? the ? function ? name ? pointed ? to ? by ? lpProcName ? must ? be ? identical ? to ? that ? in ? the ? EXPORTS ? statement ? of ? the ? source ? DLL's ? module-definition ? (.DEF) ? file. ? The ? exported ? names ? of ? Win32 ? API ? functions ? may ? differ ? from ? the ? names ? you ? use ? when ? calling ? these ? functions ? in ? your ? code. ??下面再從理論方面進行一些分析:?GetProcAddress函數聲明是:?FARPROC ? GetProcAddress(?? ? HMODULE ? hModule, ? ? ? ? // ? handle ? to ? DLL ? module?? ? LPCSTR ? lpProcName ? ? ? // ? name ? of ? function?);??
C++是支持函數重載的,也就是說允許多個不同的函數可以有同樣的函數名,如果不通過extern "C"修飾,就可以輸出相同的函數名。?這樣,就和GetProcAddress函數聲明不一致了,所以推斷不能動態調用沒有extern "C"修飾的導出函數,因為GetProcAddress函數是通過函數名來唯一確定被調用函數的地址的。??歡迎大家討論!?
第1個回答
顯示調用必須使用extern "C"修飾符。隱式調用可以使用任何類型,但只有C++能調用沒有extern "C"修飾的導出函數。?GetProcAddress是一種通用的獲取函數入口點的API,能被任何語言調用,所以限制一定比較多,比如它的參數一定是一個ANSI串(操作系統并未提供UNICODE版本)。?
第2個回答我的理解是這樣的:GetProcAddress實際上跟你直接調用myfunc()一樣,都是查詢Export表來得到函數地址再去調用,因此你修飾符不對就會造成找不到entry,是不行的。當然我沒試過,沒有完全的把握。?
第3個回答C函數和C++函數的名稱是不一樣的,可以使用工具來查看,比如Dependency ? Walker。如果你想試驗,可以根據工具看到的名稱來調用GetProcAddress試試?
第4個回答主要是就是名字的問題?有兩種例外情況可以不加extern "C":?1。如果不是用C++編譯器而是用C編譯DLL,名字不會變,可以不加extern "C"?2。如果DLL的使用者知道是用C++編譯器編譯DLL,不加extern "C"也可以,因為他知道名字改變的規則。調用GetProcAddress,把函數名字改了就是了第5個回答
C++編譯器和C編譯器編譯后生成的函數名不一樣。?GetProcAddress認為是cdecl的函數,而?編譯DLL的是VC++,所以要加一個extern "C"的修飾符?指明以cdecl的方式生成函數。?
第6個回答發現不用加extern "C"也是可以的,只要在調用端用修飾過的函數名即可,不能用原函數名。??
例子關鍵代碼如下:?----------------------------?DLL部分:?// ? This ? is ? an ? example ? of ? an ? exported ? function.?DLL1_API ? int ? __cdecl ? fnDll1(void)?{?return ? 42;?}?輸出的修飾函數名為?fnDll1@@YAHXZ?DLL1_API ? int ? __cdecl ? fnDll1(int ? a)?{?return ? 42+a;?}?輸出的修飾函數名為?fnDll1@@YAHH@Z?-----------------------------?EXE部分:?HINSTANCE ? hModule ? = ? LoadLibrary("dll1.dll");?ASSERT(hModule);?typedef ? int ? (*fnDll1)();?fnDll1 ? pfnDll1 ? = ? NULL;?//VERIFY(pfnDll1 ? = ? (fnDll1)::GetProcAddress(hModule, ? "fnDll1"));?VERIFY(pfnDll1 ? = ? (fnDll1)::GetProcAddress(hModule, ? "?fnDll1@@YAHXZ"));?ASSERT(pfnDll1() ? == ? 42);?typedef ? int ? (*fnDll2)(int);?fnDll2 ? pfnDll2 ? = ? NULL;?VERIFY(pfnDll2 ? = ? (fnDll2)::GetProcAddress(hModule, ? "?fnDll1@@YAHH@Z"));?ASSERT(pfnDll2(3) ? == ? 45);?---------------------------?這事暫時可以告一段落了,實驗還是最有力的證明。?
轉載于:https://www.cnblogs.com/whiteyun/archive/2011/07/22/2113560.html
總結
以上是生活随笔為你收集整理的通过GetProcAddress函数动态调用dll中地函数,是否必须通过extern C声明导出函数?(转)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 脚本格式及部分命令
- 下一篇: public private prote