假設這樣的情景:
一個exe加載了兩個dll(dll1和dll2,並使用隱式加載)。dll和dll2都同時向外導出一個函數:
int add(int a, int b);
如果在exe中調用了add函數,那麼它調用的會是哪個dll的add函數呢?
爲了驗證這個結果,寫了一個測試的例子。兩個dll(win32的dll)分別取名位MyDll1和MyDll2,並讓他們導出同樣的上述add函數,只是在實現的時候加了一個打印輸出,用以區分到底是哪個dll調用。
最終發現是和在工程配置中的lib順序相關的。也就是說,如果在【Link】的Object/library modules中的順序爲MyDll1.lib MyDll2.lib(MyDll1在前),主程序中調用的是MyDll1中的函數實現;相反,如果工程中配置的是MyDll2.libMyDll1.lib(MyDll2在前),主程序中調用的是MyDll2中的函數實現。
看到結果後想,這似乎是合理的。exe發現一個函數調用,而且是在dll中的。它就會遍歷自己所加載的dll去搜索,這個應該就是順序關鍵性的所在,找到第一個匹配的,就執行調用。所以,誰在前,調用誰。
對此情形,想到另外一個問題。對於較大的程序來說,往往要分成若干個模塊。而常常爲了接口的統一,需要在dll中導出相同的函數。那麼主程序怎麼才能調用想要執行的模塊中對應的函數呢?
一個最簡單也直接的辦法就是使用動態加載,並在LoadLibrary後,使用GetProcAddress。
加載DLL的方法主要有兩種:一種是隱式鏈接,另外一種是動態加載。
動態調用動態庫步驟:
1、創建一個函數指針,其指針數據類型要與調用的DLL引出函數相吻合。
2、通過Win32 API函數LoadLibrary()顯式的調用DLL,此函數返回DLL的實例句柄。
3、通過Win32 API函數GetProcAddress()獲取要調用的DLL的函數地址,把結果賦給自定義函數的指針類型。
4、使用函數指針來調用DLL函數。
5、最後調用完成後,通過Win32 API函數FreeLibrary()釋放DLL函數。
例如:
假設函數的聲明爲:void message(int a);
//函數指針聲明
typedef void (WINAPI MESSAGE)(int a);
MESSAGE *pMessage = 0;
//加載a.dll
HINSTANCE hDLLDrv = LoadLibrary("a.dll");
//獲取message函數的指針
if(hDLLDrv)
{
pMessage = (MESSAGE *)GetProcAddress(hDLLDrv, "message");
}
然後就可以這樣調用函數了:
pMessage(1);