Win32下動態鏈結庫 DLL 程式設計

2021-04-13 08:17:09 字數 3850 閱讀 3320

主題:dll是windows最重要的組成要素,windows中的許多新功能、新特性都是通過dll來

實現的,因此掌握它、應用它是非常重要的。

動態鏈結庫不僅可以作為乙個執行模組,包括函式**,而且可以包含程式以外的任何資料

或資源(位圖、圖示等等)。動態鏈結庫就是給應用程式提供函式或者資源。

dll是一種磁碟檔案(通常帶有dll副檔名),它由全域性資料、服務函式和資源組成,

在執行時被系統載入到程序的虛擬空間中,成為呼叫程序的一部分。在執行時,只有當exe

程式確實要呼叫這些dll模組的情況下,系統才會將它們裝載到記憶體空間中。每個程序都復

制了自己的讀/寫全域性變數。如果想要與其它程序共享記憶體,必須使用記憶體對映檔案或者聲

明乙個共享資料段。dll模組需要的堆疊記憶體都是從執行程序的堆疊中分配出來的。

dll檔案中包含乙個匯出函式表。這些匯出函式由它們的符號名和稱為標識號的整數與外界聯絡起來。

匯入匯出函式:

在dll**中,必須像下面這樣明確宣告匯出函式:

__declspec(dllexport) int myfunction(int n);

但也可以在模組定義(def)檔案中列出匯出函式,不過這樣做常常引起更多的麻煩。在應用程式方面,要

求像下面這樣明確宣告相應的輸入函式:

__declspec(dllimport) int myfuncition(int n); (這是隱式鏈結dll)

僅有匯入和匯出宣告並不能使應用程式內部的函式呼叫鏈結到相應的dll檔案上。應用程式的專案必須為

鏈結程式指定所需的輸入庫(lib檔案)。而且應用程式事實上必須至少包含乙個對dll函式的呼叫。

隱式鏈結和顯式鏈結dll

顯式:typedef double(sqrtproc)(double);

hinstance hinstance; //設定全域性變數用於儲存dll控制代碼

sqrtproc* pfunction; 第二個變數showme是指向dll,庫中函式的指標

verify(hinstance=::loadlibrary("c://winnt//system32//mydll.dll"));

verify(pfunction=(sqrtproc*)::getprocaddress(hinstance,"squareroot"));

double d=(*pfunction)(81.0);//呼叫該dll函式

隱式: 程式設計師通過靜態鏈結方式編譯生成應用程式時,應用程式中的呼叫函式與lib檔案中匯出符號相

匹配,這些符號或標識號進入到生成的exe檔案中.

隱式鏈結和顯式鏈結dll的區別:

在隱式鏈結方式中,所有被應用程式呼叫的dll檔案都會在應用程式exe檔案載入時被載入在到記憶體中;但

如果採用顯式鏈結方式,程式設計師可以決定dll檔案何時載入或不載入。

dllmain函式:

當windows載入dll模組時呼叫這一函式。系統首先呼叫全域性物件的建構函式,然後呼叫全域性函式dllmain。

dllmain函式不僅在將dll鏈結載入到程序時被呼叫,在dll模組與程序分離時(以及其它時候)也被呼叫。

程序中的每個dll模組被全域性唯一的32位元組的hinstance控制代碼標識。程序自己還有乙個hinstance控制代碼。所

有這些模組控制代碼都只有在特定的程序內部有效,它們代表了dll或exe模組在程序虛擬空間中的起始位址。

尋找dll的路徑:

windows將遵循下面的搜尋順序來定位dll:

1. 包含exe檔案的目錄,

2. 程序的當前工作目錄,

3. windows系統目錄,

4. windows目錄,

5. 列在path環境變數中的一系列目錄。

要點:一:dll檔案的省缺名稱是與工程名一致的(也是在.def檔案中library 之後的名字),不要試圖在製作完畢之後通

過簡單的修改.dll檔案的檔名來改變它,這會導致使用該dll的應用程式錯誤.

dll中定義有兩種函式:

匯出函式(exportfunction): 可以被其他模組呼叫

內部函式(internalfunction): 只能在dll內部使用

基於mfc的dll不適用與製作讀取二進位制檔案的dll (不易移植,無法正確讀取與dos應用程式共享的二進位制檔案)

基於api的dll可以正確讀取在dos環境中建立的二進位制檔案.

純標準函式dll可以在很多平台使用!(移植性最強)

為了讓其它語言使用:除非你絕對需要使用c++編碼,否則我還是推薦使用c來寫dll。

vc下的dll型別:

non-mfc dll:指的是不用mfc的類庫結構,直接用c語言寫的dll,其輸出的函式一

般用的是標準c介面,並能被非mfc或mfc編寫的應用程式所呼叫。ll,

所有從dll輸出的函式應該以如下語句開始:

afx_manage_state(afxgetstaticmodulestate( ))

此語句用來正確地切換mfc模組狀態。

在製作dll時,vc++對函式的省缺宣告是"__cedcl",也就是說,如果你在宣告你的函式時不作特殊宣告的話,你

製作的dll將只能被c/c++呼叫,如果你想用其他開發語言(比如vb5.0)呼叫它就會報錯,即使呼叫方法完全正確.

二:宣告型別詳解:

三:制dll所要的檔案:

模 塊 定 義 文 件(.def) 是 由 一 個 或 者 多 個 用 於 描 述dll 屬 性 的 模 塊 語 句 組 成

的 文 本 文 件, 每 個.def 文 件 至 少 必 須 包 含 以 下 模 塊 定 義 語 句:

第 一 個 語 句 必 須 是library 語 句, 指 出dll 的 名 字。

exports 語 句 列 出 被 導 出 函 數 的 名 字。

可 以 使 用description 語 句 描 述dll 的 用 途( 此 句 可 選)。

";" 對 一 行 進 行 注 釋( 可 選)

實 現 文 件(.cpp 文 件 為 例)

實 現 入 口 表 函 數 的.cpp 文 件 中, 包 含dll 入 口 點 處 理 的api 函 數 和 導 出 函 數 的 代 碼。

四:介紹non-mfc dlls的編寫方法:如果用vc的嚮導那就很方便了!

寫法:bool apientry dllmain(handle hmodule,dword ul_reason_for_call,

lpvoid lpreserved)

switch( ul_reason_for_call )

每乙個dll必須有乙個入口點,這就象我們用c編寫的應用程式一樣,

必須有乙個winmain函式一樣。

在這個示例中,dllmain是乙個預設的入口函式,你不需要編寫自己

的dll入口函式,並用linker的命令列的引數開關/entry宣告。用這個缺

省的入口函式就能使動態連線庫被呼叫時得到正確的初始化,當然了,你

不要在初始化的時候填寫使系統崩潰的**了。

引數中,hmoudle是動態庫被呼叫時所傳遞來的乙個指向自己的控制代碼

(實際上,它是指向_dgroup段的乙個選擇符)

ul_reason_for_call是乙個說明動態庫被調原因的標誌。當程序或執行緒

裝入或解除安裝動態連線庫的時候,作業系統呼叫入口函式,並說明動態連線庫

被呼叫的原因。它所有的可能值為:

dll_process_attach: 程序被呼叫

dll_thread_attach: 執行緒被呼叫

dll_process_detach: 程序被停止

dll_thread_detach: 執行緒被停止

lpreserved是乙個被系統所保留的引數。

入口函式已經寫了,餘下的也不難,你可以在檔案中加入你所想要輸

出的函式或變數或c++類等

五:純資源dll的編寫

Win32 動態鏈結庫 二

1.檔案 新建 空專案 include windows.h include stdio.h pragma comment lib,debug xxp dll test.lib extern c declspec dllimport int addfun int a,int b 匯入動態鏈結庫的add...

MFC動態鏈結庫和WIN32動態鏈結庫

1 dll的構成 每個應用程式都有乙個入口函式winmain,而每個dll也有乙個入口函式dllmain。dll跟應用程式一樣都含有資源 資料段和 段。dll跟應用程式的差別主要是dll有符號輸入表和符號輸出表,以方便應用程式呼叫dll中的函式。因為dll是由應用程式載入的,所以它本身沒有虛擬的記憶...

WIN32 DLL動態鏈結庫

win32 dll建立動態鏈結庫.步驟如下 1 先開發乙個dll動態鏈結庫 程式如下 include messagebox null,retstr,read info mb ok declspec dllexport void stdcall writeregpara lpctstr lpvalue...