DLL動態庫動態載入

一月一星辰發表於2024-08-28

庫的呼叫方式

在VS下呼叫庫有兩種形式:
- 靜態載入
- 動態載入
靜態載入下,對應的標頭檔案、DLL和LIB缺一不可,並且產生的EXE沒有找到DLL檔案的話就會導致“應用程式初始化失敗”。
動態載入下,只需要DLL,透過LoadLibrary()函式進行載入,但該方式對生成的dll的規範有一定的要求否則容易出錯。
下面主要介紹如何正常動態載入呼叫DLL。

動態載入

1. LoadLibrary是用來載入dll的,格式為

 HINSTANCE hdll;
 hdll=LoadLibrary("Image Enhance.dll");

呼叫成功後返回函式地址,否則返回0或NULL

[!NOTE] 錯誤原因和解決方法
1.路徑不對(程式與dll要放在同一資料夾)
2.dll本身錯誤(依賴其他dll)藉助depends.exe檢視DLL依賴那些DLL
2. GetProcAddress()是用來獲取函式地址的,格式為:

 fun1 =(DLLfun)GetProcAddress(hdll, "sharpen"); 

呼叫成功後返回函式地址,否則返回0或NULL

[!NOTE] 錯誤原因和解決方法
當返回為0時,可以使用depends.exe工具來檢視DLL裡函式介面的具體的名字,可以發現會出現這種“?? 0sharpen @@QAE@XZ”奇怪的命名方式,軟體上可以試著吧這個段替換原函式名測試一下,發現執行應該就正常了。
但是這種方式呼叫起來很不方式,其實這是建立的DLL庫時,寫的程式碼不夠規範。
標頭檔案中定義__declspec(dllexport) 時,要加上extern "C",從而規範dll的輸出符合C標準,否則容易生成帶@之類的字串。extern"C"使得在C++中使用C編譯方式成為可能。在“C++”下定義“C”函式,需要加extern“C”關鍵詞。用extern "C"來指明該函式使用C編譯方式。加上extern “C”後,輸出函式的形式為"sharpen",符合預期標準。
其他標準可以參考:dll 匯出函式名的那些事_vs dll函式名不一致-CSDN部落格

 #define IMG_EXPORTS extern "C" __declspec(dllexport) 
//或者 extern "C" _declspec(dllimport) int calculateLineNum(CString filePath); 

3. FreeLibrary()是用來釋放載入dll時佔用的空間的,由於Loadlibrary()為對dll的顯式載入(又叫動態載入),這種方式不會在用完dll後自動清理dll所佔用的空間,所以我們要手動清除dll所佔用的空間。否則會導致記憶體洩漏。呼叫格式如下:

FreeLibrary(hdll); 

參考連結:VS下動態庫dll的顯式呼叫(動態呼叫)_vs專案dll顯式載入-CSDN部落格

相關文章