DLL程式設計技術

2021-06-16 07:22:56 字數 4788 閱讀 1887

一、dll原理

dll(dynamic link library)也就是「動態鏈結庫」,是乙個可以被其它應用程式共享的程式模組,其中封裝了一些可以被共享的程式或資源。它雖然包含了可執行**卻不能單獨執行,而應由相應的應用程式直接或間接呼叫。在 windows 32 中,可以將 dll 標記為共享以導致相同的行為。但是,每個程序的預設設定是擁有 dll 資料的專用副本。以.dll、.drv、.fon、.sys為副檔名和許多以 .exe 為副檔名的系統檔案都可以是 dll。

dll可以有自己的資料段,但沒有自己的堆疊,使用與呼叫它的應用程式相同的堆疊模式;乙個dll在記憶體中只有乙個例項;dll實現了**封裝性;dll的編制與具體的程式語言及編譯器無關,可以通過dll來實現混合語言程式設計。dll函式中的**所建立的任何物件(包括變數)都歸呼叫它的執行緒或程序所有。

二、呼叫約定和名字修飾約定

呼叫約定(calling convention):決定函式引數傳送時入棧和出棧的順序,由呼叫者還是被呼叫者把引數彈出棧,以及編譯器用來識別函式名字的修飾約定。

1.__stdcall 是 pascal 程式的預設呼叫方式,通常用於 win32 api 中,函式採用從右到左的壓棧方式,自己在退出時清空堆疊。vc 將函式編譯後會在函式名前面加上下劃線字首,在函式名後加上 "@" 和引數的位元組數。

2.__cdecl 是 c 和 c++ 程式預設的呼叫方式。每乙個呼叫它的函式都包含清空堆疊的**,所以產生的可執行檔案大小會比呼叫 _stdcall 函式的大。函式採用從右到左的壓棧方式,由呼叫者把引數彈出棧。vc 將函式編譯後僅僅在函式名前面加上下劃線字首。 它是 mfc 預設呼叫約定。 

3.__fastcall方式的函式採用暫存器傳遞引數(實際上,它用 ecx 和 edx 傳送前兩個雙字(dword)或更小的引數,剩下的引數仍舊自右向左壓棧傳送,被呼叫的函式在返回前清理傳送引數的記憶體棧),vc 將函式編譯後會在函式名前面加上"@"字首,在函式名後加上"@"和引數的位元組數。

5.naked call採用 1-4 的呼叫約定時,如果必要的話,進入函式時編譯器會產生**來儲存esi,edi,ebx,ebp暫存器,退出函式時則產生**恢復這些暫存器的內容。naked call不是型別修飾符,故必須和__declspec 共同使用。

關鍵字 __stdcall、__cdecl 和 __fastcall 可以直接加在要輸出的函式前,也可以在編譯環境的 setting...\c/c++ \code generation 項選擇。當加在輸出函式前的關鍵字與編譯環境中的選擇不同時,直接加在輸出函式前的關鍵字有效。它們對應的命令列引數分別為/gz、/gd 和 /gr。預設狀態為/gd,即_cdecl。

"c" 或者 "c++" 函式在內部(編譯和鏈結)通過修飾名識別。修飾名是編譯器在編譯函式定義或者原型時生成的字串。

a、c編譯時函式名修飾約定規則: 

__stdcall 呼叫約定在輸出函式名前加上乙個下劃線字首,後面加上乙個"@"符號和其引數的位元組數,格式為 _functionname@number。 

__cdecl呼叫約定僅在輸出函式名前加上乙個下劃線字首,格式為 _functionname。 

__fastcall呼叫約定在輸出函式名前加上乙個"@"符號,後面也是乙個"@"符號和其引數的位元組數,格式為@functionname@number。

b、c++編譯時函式名修飾約定規則:

__stdcall呼叫約定的格式為"?functionname@@yg*****@z"或"?functionname@@yg*xz",以"?"標識函式名的開始,後跟函式名;函式名後面以"@@yg"標識參數列的開始,後跟參數列;參數列以代號表示:x——void,d——char,e——unsigned char,……,pa——表示指標,後面的代號表明指標型別,如果相同型別的指標連續出現,以"0"代替,乙個"0"代表一次重複;參數列的第一項為該函式的返回值型別,其後依次為引數的資料型別,指標標識在其所指資料型別前;參數列後以"@z"標識整個名字的結束,如果該函式無引數,則以"xz"標識結束。 

__cdecl呼叫約定規則同上面的__stdcall呼叫約定,只是參數列的開始標識由上面的"@@yg"變為"@@ya"。 

__fastcall呼叫約定規則同上面的__stdcall呼叫約定,只是參數列的開始標識由上面的"@@yg"變為"@@yi"。

三、dll工程

vc6中可以直接使用win32 dll開始dll的編寫。這種方法是沒有mfc支援,直接使用win32 api來完成的。

vc6中有三種形式的mfc dll可供選擇,即regular statically linked to mfc dll(標準靜態鏈結mfc dll)、regular using the shared mfc dll(標準動態鏈結mfc dll)以及extension mfc dll(擴充套件mfc dll)。第一種dll在編譯時把使用的mfc**鏈結到dll中,執行程式時不需要其他mfc動態鏈結類庫的支援,但體積較大;第二種dll在執行時動態鏈結到mfc類庫,因而體積較小,但卻依賴於mfc動態鏈結類庫的支援;這兩種dll均可被mfc程式和win32程式使用。第三種dll的也是動態連線,但做為mfc類庫的擴充套件,只能被mfc程式使用。 

輸出函式的方法有以下幾種: 

1、傳統的方法 

在模組定義檔案的 export 部分指定要輸入的函式或者變數。語法格式如下: 

entryname[=internalname] [@ordinal[noname]] [data] [private] 

其中: 

entryname 是輸出的函式或者資料被引用的名稱; 

internalname 同 entryname; 

@ordinal 表示在輸出表中的順序號(index); 

noname 僅僅在按順序號輸出時被使用(不使用 entryname );

data 表示輸出的是資料項,使用 dll 輸出資料的程式必須宣告該資料項為 _declspec(dllimport)。

上述各項中,只有 entryname 項是必須的,其他可以省略。

對於"c"函式來說,entryname 可以等同於函式名;但是對 "c++" 函式(成員函式、非成員函式)來說,entryname 是修飾名。可以從 .map 映像檔案中得到要輸出函式的修飾名,或者用vc的bin目錄中的dumpbin /symbols 得到,然後把它們寫在 .def 檔案的輸出模組。 

如果要輸出乙個 "c++" 類,則把要輸出的資料和成員的修飾名都寫入 .def 模組定義檔案。

2、在命令列輸出 

對鏈結程式 link 指定 /export 命令列引數,輸出有關函式。 

3、使用 mfc 提供的修飾符號 _declspec(dllexport) 

例如,在乙個 c++ 檔案中,有如下函式: 

extern "c"  

其輸出函式名為:test 

mfc提供了一些巨集,就有這樣的作用。

afx_class_import:__declspec(dllexport) 

afx_api_import:__declspec(dllexport) 

afx_data_import:__declspec(dllexport) 

afx_class_export:__declspec(dllexport) 

afx_api_export:__declspec(dllexport) 

afx_data_export:__declspec(dllexport) 

afx_ext_class: #ifdef _afxext 

afx_class_export 

#else 

afx_class_import 

afx_ext_api:#ifdef _afxext 

afx_api_export 

#else 

afx_api_import 

afx_ext_data:#ifdef _afxext 

afx_data_export 

#else 

afx_data_import 

四、呼叫dll

可以通過下列方式呼叫 dll 中的函式:

1.靜態呼叫,也稱為隱式呼叫,是在程式載入時載入dll。這種方式由編譯系統完成對dll的載入和當應用程式結束時dll解除安裝的編碼(windows系統負責對dll呼叫次數的計數),呼叫方式簡單,能夠滿足通常的要求。通常採用的呼叫方式是把產生動態連線庫時產生的.lib檔案加入到應用程式的工程中,想使用dll中的函式時,只須在原始檔中宣告一下。

lib檔案包含了每乙個dll匯出函式的符號名和可選擇的標識號以及dll檔名,不含有實際的**。

2.動態呼叫,即顯式呼叫方式,是在程式執行時載入dll。這種方式是由程式設計者用api函式載入和解除安裝dll來達到呼叫dll的目的,比較複雜,但能更加有效地使用記憶體,是編制大型應用程式時的重要方式。

在windows系統中,與動態庫呼叫有關的函式包括: 

loadlibrary(或mfc 的afxloadlibrary),裝載動態庫。

getprocaddress,獲取要引入的函式,將符號名或標識號轉換為dll內部位址。需要函式的修飾名為引數,可以使用vc自帶的工具depends檢視相應的dll來得到。

freelibrary(或mfc的afxfreelibrary),釋放動態鏈結庫。

在鏈結時,windows 首先搜尋預安裝的一組 dll,例如效能庫 (kernel32.dll) 和安全庫 (user32.dll)。然後,windows 按以下順序搜尋 dll: 

1. 當前程序的可執行程式所在的目錄。 

2. 當前目錄。 

3. windows 系統目錄。(getsystemdirectory 函式獲取 windows 系統目錄的路徑。) 

4. windows 目錄。(getwindowsdirectory 函式獲取 windows 目錄的路徑。) 

5. path 環境變數中列出的目錄。 

DEV Windows下DLL程式設計技術及應用

windows下dll程式設計技術及應用 一 引 言 由於windows為微機提供了前所未有的標準使用者介面 圖形處理能力和簡單靈便的操作,絕大多數程式編制人員都已轉向或正在轉向windows程式設計。在許多使用者設計的實際應用系統的程式設計任務中,常常要實現軟體對硬體資源和記憶體資源的訪問,例如埠...

Windows下DLL程式設計技術及應用

一 引 言 由於windows為微機提供了前所未有的標準使用者介面 圖形處理能力和簡單靈便的操作,絕大多數程式編制人員都已轉向或正在轉向windows程式設計。在許多使用者設計的實際應用系統的程式設計任務中,常常要實現軟體對硬體資源和記憶體資源的訪問,例如埠i o dma 中斷 直接記憶體訪問等等。...

Nios Flash程式設計技術

1.1 altera支援cfi flash程式設計 1.3 非支援cfi程式設計 由於我所用的nor flash晶元是am29lv320db,不再nios支援的列表,自己編輯了override檔案,但還是無法正確program進去,決定用列表支援的sst39vf800試一試,引腳相容,容量為1 4,...