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