動態連接庫不能直接運行,也不能接收消息。它們是一些獨立的文件,其中包含能被可執行程序或其它DLL調用來完成某項工做的函數或是數據。只有在其它模塊調用動態連接庫中的函數時,它才發揮做用。Windows API中的全部函數都包含在DLL中。其中有3個最重要的DLL,Kernel32.dll,它包含用於管理內存、進程和線程的各個函數;User32.dll,它包含用於執行用戶界面任務(如窗口的建立和消息的傳送)的各個函數;GDI32.dll,它包含用於畫圖和顯示文本的各個函數。函數
動態連接庫有兩種加載方式測試
1.隱式連接spa
2.顯示加載線程
下面咱們來分別介紹一下這兩種方式:指針
咱們首先定義兩個簡單的測試函數orm
int _stdcall add(int a,int b)進程
{ return a+b; }內存
int _stdcall subtract(int a,int b)ci
{ return a-b; }編譯
因爲DLL的函數必須導出後纔可已使用因此在兩個函數前面都加上導出符_declspec(dllexport)
_declspec(dllexport) int _stdcall add(int a,int b)
{ return a+b; }
_declspec(dllexport) int _stdcall subtract(int a,int b)
{ return a-b; }
或者是定義模塊定義文件.def進行導出
LIBRARY DllName
EXPORTS
add
subtract
什麼?還不明白這裏是怎麼回事?那麼請參考 C++建立一個動態連接庫
編譯後會生成兩個可用的文件一個是lib文件一個是dll文件,那麼這個lib文件是幹嗎的呢?
靜態庫:函數和數據被編譯進一個二進制文件(一般擴展名爲.LIB)。在使用靜態庫的狀況下,在編譯連接可執行文件時,連接器從庫中複製這些函數和數據並把它們和應用程序的其它模塊組合起來建立最終的可執行文件(.EXE文件)。
在使用動態庫的時候,每每提供兩個文件:一個引入庫和一個DLL。引入庫包含被DLL導出的函數和變量的符號名,DLL包含實際的函數和數據。在編譯連接可執行文件時,只須要連接引入庫,DLL中的函數代碼和數據並不複製到可執行文件中,在運行的時候,再去加載DLL,訪問DLL中導出的函數。
這下明白了吧。
因爲這個文件包含了導出函數的符號名,爲了在工程中使用這些導出函數對於隱式連接咱們須要先將這個lib文件引入到工程,在工程屬性中選擇 鏈接器->輸入->附加依賴項中添加這個文件。
使用時工程包含DLL頭文件(包含了咱們要調用的DDL導出函數的聲明),這樣咱們就能夠直接使用DLL中的導出函數了。
對於顯示鏈接,即動態加載咱們須要調用LoadLibrary
在MSDN中:
HMODULE WINAPI LoadLibrary(
__in LPCTSTR lpFileName
);
Maps the specified executable module into the address space of the calling process.
意思就是說它的功能是映射一個可執行模塊到調用進程的地址空間。具體方法以下:
MFC代碼
HINSTANCE hInst;
hInst=LoadLibrary("Dll3.dll");//將Dll3加載,映射到地址空間 typedef int (/*_stdcall*/ *addFunPro)(int a,int b);//此處是定義一個跟導出函數類型形同的函數指針,用來保存函數地址 addFunPro AddFun=(addFunPro)GetProcAddress(hInst,MAKEINTRESOURCE(1));//得到導出函數的地址 if(!AddFun)
{ MessageBox("獲取函數地址失敗!"); return;
}
CString str;
str.Format("5+3=%d",AddFun(5,3));//調用導出函數,執行加法操做 MessageBox(str);
FreeLibrary(hInst);