Windows開發之動態庫載入
前段時間寫程式碼,主程序要載入很多dll,剛開始寫的dll動態載入,好麻煩的說。老大說寫成靜態載入,理解錯了意思,改成了靜態庫,真的傻。好長時間沒寫動態庫,忘得差不多了,筆記裡也是簡單記了下。最後改成了個dll靜態載入,現在來總結一下吧。
動態庫,在Windows下為dll檔案,Linux下是so,這裡先不討論。dll檔案即可執行檔案的一種,也是就PE檔案,還有一種常見的PE檔案格式就是exe檔案,也就是Windows程式。動態庫不能單獨執行,必須載入到某一程序中,動態庫的載入可分為靜態載入和動態載入。在程式里加載動態庫叫載入,向其他程式載入動態庫就叫注入了,這個後邊再寫。
1.動態載入
動態載入也是執行時載入,是在程式執行到載入語句的時候才會載入動態庫,動態載入呼叫api介面LoadLibrary。
HMODULE LoadLibraryA(
LPCSTR lpLibFileName
);
介面返回動態庫控制代碼,接著呼叫GetProcAddress,獲得匯出函式地址,載入動態庫的目的就是呼叫動態庫中的介面。
FARPROC GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
);
返回函式地址,再次之前要使用typedef定義函式型別,為指向匯出函式的指標。函式返回值和形參和匯出函式相同。接著就可以用呼叫定義的函式方式呼叫匯出函式。
最後使用FreeLibrary釋放模組控制代碼。
BOOL FreeLibrary( HMODULE hLibModule );
在動態庫中要在要匯出的函式前面加
extern "C" _declspec(dllexport)
動態載入的另一種方式是def檔案,這個還沒見過,以後再補充吧。上述的動態載入過程只需要提供dll檔案。
2.靜態載入
靜態載入是在函式的編譯時候就將模組程式碼載入到程式中。靜態載入也有兩種方式,一種是def檔案,另一種是_declspec(dllexport)
1)def檔案
def檔案的格式如下:
LIBRARY MoudleName EXPORTS Function1 @1 Function2 @2 ...
在使用時在檔案頭加上下面這句,需要提供包括生成的.lib和.dll檔案,編譯時不需要標頭檔案,提供標頭檔案可以告訴別人呼叫那些介面
#pragma comment(lib,"DllName.lib")
在動態庫的函式中需要加上WINAPI呼叫約定,這是我遇到的問題,沒有呼叫約定會不認識。
2)_declspec(dllexport)
在動態庫的匯出函式前加
extern "C" _declspec(dllexport)
使用時在檔案前面加上
#include "DllName.h" #pragma comment(lib,"DllName.lib") extern "C" _declspec(dllexport) Function()
這種載入方式需要提供標頭檔案、lib檔案和dll檔案。
lib檔案為動態庫的匯入庫,提供給程式函式地址符號等,並不是靜態庫。