1. 程式人生 > >Windows開發之動態庫載入

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檔案為動態庫的匯入庫,提供給程式函式地址符號等,並不是靜態庫。