程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 動態鏈接庫的兩種調用方式

C++ 動態鏈接庫的兩種調用方式

編輯:C++入門知識

動態鏈接庫不能直接運行,也不能接收消息。它們是一些獨立的文件,其中包含能被可執行程序或其它DLL調用來完成某項工作的函數或是數據。只有在其它模塊調用動態鏈接庫中的函數時,它才發揮作用。Windows API中的所有函數都包含在DLL中。其中有3個最重要的DLL,Kernel32.dll,它包含用於管理內存、進程和線程的各個函數;User32.dll,它包含用於執行用戶界面任務(如窗口的創建和消息的傳送)的各個函數;GDI32.dll,它包含用於畫圖和顯示文本的各個函數。
動態鏈接庫有兩種加載方式
1.隱式鏈接
2.顯示加載
下面我們來分別介紹一下這兩種方式:

我們首先定義兩個簡單的測試函數


[cpp]
int _stdcall add(int a,int b) 

    return a+b; 

 
int _stdcall subtract(int a,int b) 

    return a-b; 

int _stdcall add(int a,int b)
{
 return a+b;
}

int _stdcall subtract(int a,int b)
{
 return a-b;
}

由於DLL的函數必須導出後才可已使用所以在兩個函數前面都加上導出符_declspec(dllexport)


[cpp]
_declspec(dllexport) int _stdcall add(int a,int b) 

    return a+b; 

 
_declspec(dllexport) int _stdcall subtract(int a,int b) 

    return a-b; 

_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代碼


[cpp]
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); 

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);

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved