一、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,...