動態鏈接庫

30 篇文章 0 订阅
15 篇文章 0 订阅


---------------------------------2016.09.10------------------------------------------
---------------------------------動態鏈接庫------------------------------------------

動態鏈接庫DLL(Dynamic-Link Library)

Kernel32.dll 包含用於管理內存,進程和線程的函數(CreateThread)。
User32.dll 包含用於執行用戶界面任務的函數(eg:CreateWindow)。
GDI32.dll 包含用於畫圖和顯示文本的函數。

靜態庫:函數與數據被編譯進一個二進制文件(.lib)

編譯鏈接可執行程序時,將lib中的內容複製,並把它們和應用程序的其他模塊結合起來創建最終的可執行文件.exe
發佈使勁發佈.exe文件即可。

動態庫:使用動態庫時,提供一個引入庫文件.lib(包含該DLL導出的函數和變量的符號名)和一個.dll文件(包含該DLL實際的函數和數據)

編譯鏈接時,只連接該DLL的引入庫文件,運行時加載所需的DLL,將其映射到進程的地址空間。
發佈時還需要發佈要調用的動態鏈接庫。
-----------------------------------------------------------------------------------------------------
dll的優勢:
可採用多種編程語言來編寫
增強產品功能
提供二次開發的平台
簡化項目管理
節省磁盤空間與內存
有助於資源共享
有助於實現應用程序本地化
-----------------------------------------------------------------------------------------------
動態鏈接庫加載有隱式加載和顯式加載兩種方式。
-------------------------------------------------------------------------------------------------
應用程序如果想要訪問某個DLL文件中的函數,那麼該函數必須是已經被導出的函數。
查看一個DLL中有哪些導出函數,可用Dunpbin實現。

為了讓DLL導出一些函數,有兩種方式:
1.在每一個將要被導出的函數前面加上標識符:_declspec(dllexport)
eg:    _declspec(dllexport) int add(int a,int b)
    {
        return a+b;
    }
    _declspec(dllexport) int sustract(int a,int b)
    {
        return a-b;
    }

2.一中採用模塊定義(.def)文件聲明,需要在庫工程中添加模塊文件,格式如下:
 
LIBRARY 庫工程名稱
 
EXPORTS 導出函數名
------------------------------------------------------------------------------
_declspec(dllimport)標識符來表明函數是從動態鏈接庫引入的。

-------------------------------------------------------------------------------
dumpbin 命令:
---------------
dumpbin -exports *.dll

信息列表中:
ordinal列列出的信息是導出函數的序號;
hint列列出的數字是提示碼;
RVA列列出的地址值時導出函數在DLL模塊中的位置,即通過該地址值,可以在DLL中找到它們。
name列列出的是導出函數的名稱(會出現名字改變現象)。
-------------------------------------------------------------------------------------------------
C++支持函數重載,對於重載的多個函數來說,其函數名都是一樣的,為了加以區分,在編譯鏈接時,C++會按照
自己的規則改變函數的名稱——名字改編、名字粉碎

解決的方法:
在定義導出函數時,加上限定符:external"C".字母C一定要大寫。
經過此操作的只能用於導出全局函數這種情況,不能導出類的成員函數。

標準調用約定:_stdcall;

在函數體與聲明前加上 _stdcall可以實現導出類的成員函數,但是又會出現名字改編問題;

模塊定義文件*.def

可以通過模塊定義文件的方式來解決名字改編問題。
------------------------------------------------------------------------------------
文件內部格式:

LIBRARY <動態鏈接庫內部名稱>

EXPORTS

//表明DLL將要導出的函數,以及為這些導出函數指定的符號名
<函數名>

---------------------------------------------------------
如果將要導出的符號名和原文件中定義的函數名不一樣,則可以按照 entryname = internalname 方法指定導出函數;

entryname :導出的符號名;
internalname :DLL中將要導出的函數的名字。
------------------------------------------------------------------------------------------------------

隱式鏈接方式加載DLL
--------------------

當應用程序需要調用某個動態鏈接庫時,在程序鏈接時只需要包含該動態鏈接庫提供的輸入文件庫即可。
當應用程序運行時,系統為其分配地址空間,然後加載模塊會分析該應用程序的輸入信息,從中找出該
程序要訪問的動態鏈接庫信息,然後在用戶機器上搜索這些動態鏈接庫,進而加載它們。
搜索的順序依次是:
》程序的執行目錄..\\Denug
》當前目錄“.”
》系統目錄 依次是:C:\WINNT\system32,C:\WINNT\system,C:\WINNT
》path環境變量中所列出的路徑
----------------------------------------------------------------------------

顯式鏈接方式加載DLL
--------------------
將生成的 *.dll 和 *.lib 文件複製到要調用動態鏈接庫的函數執行目錄中;

使用 LoadLibrary函數。將指定的可執行模塊映射到調用進程的地址空間。

HMODULE LoadLibrary(
           
           LPCTSTR lpFileName//指定可執行模塊的名稱        

           )

該函數可以加載 *.dll 文件和 *.exe 文件。

返回值類型是 HMODULE.(HMODULE 類型和 HINSTAANCE 類型可以通用)

獲取到動態鏈接庫的句柄后,使用 GetProcAddress 函數獲得蓋動態鏈接庫中導出函數的地址,

函數原型:

FARPROC GetProcAddress(

            HMODULE hModule,//指定動態鏈接庫模塊的句柄(LoadLibrary 的返回值)
            
            LPCTSTR lpProcName//指定 DLL 導出的函數的名字或函數的序號

            )

在獲取函數的返回值時,要進行強制轉換,轉換成 ADDPROC 類型。

應使用標準調用約定 _stdcall 在需要的地方。

即,當 DLL 中導出函數採用的是標準調用約定時,訪問該 DLL 的客戶端程序也應該採用約定類型來訪問相應的導出函數。

---------------------------------------------------------------------------------------------------------------
根據序號訪問 dll 中的導出函數

MAKEINTRESOURCE 宏:將指定的函數序號轉換為相應函數名字字符串。

----------------------------------------------------------------------------------

隱式鏈接方式與顯式連接方式的區別:

隱式鏈接方式:直接加載,隨時調用;

顯式連接方式:使用時加載;

-------------------------------------------------------------------------------
DllMain函數:Dll入口函數。類似於可執行模塊的 WinMain

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module,動態鏈接庫模塊的句柄
    DWORD fdwReason,     // reason for calling function,標記值,用來指示調用該 DLL 入口函數的原因。
    LPVOID lpReserved )  // reserved,保留參數,若 DLL 被動態加載,則參數為 NULL;若被靜態加載,則為非 NULL.

----------------------------------------------------------------------------------------
FreeLibrary
-----------

BOOL FreeLibrary(HMODULE hModule);//參數指定將要釋放的那個 DLL 的模塊句柄。

若採用動態加載方式調用DLL時,在需要訪問時,調用 LoadLibrary 函數加載該 DLL;
當不再需要訪問該 DLL 時,調用 FreeLibrary 函數釋放對該 DLL 的引用。


--------------------------------未完----------------------------------------------
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值