?? 如何在vc++6_0中使用動態(tài)連接庫中級樂園編程技術(shù)it與數(shù)碼uum社區(qū).htm
字號:
<TR vAlign=top height=100>
<TD style="WIDTH: 600px; WORD-BREAK: break-all"
colSpan=3><SPAN
id=lblSubjectContents>動態(tài)鏈接庫的創(chuàng)建<BR>>>>>在Visual
C++6.0開發(fā)環(huán)境下,打開FileNewProject選項,可以選擇Win32 Dynamic-Link
Library或MFC AppWizard[dll]來以不同的方式來創(chuàng)建Non-MFC Dll、Regular
Dll、Extension Dll等不同種類的動態(tài)鏈接庫。<BR>>>>>1.
Win32 Dynamic-Link Library方式創(chuàng)建Non-MFC
DLL動態(tài)鏈接庫<BR>>>>>每一個DLL必須有一個入口點,這就象我們用C編寫的應(yīng)用程序一樣,必須有一個WINMAIN函數(shù)一樣。在Non-MFC
DLL中DllMain是一個缺省的入口函數(shù),你不需要編寫自己的DLL入口函數(shù),用這個缺省的入口函數(shù)就能使動態(tài)鏈接庫被調(diào)用時得到正確的初始化。如果應(yīng)用程序的DLL需要分配額外的內(nèi)存或資源時,或者說需要對每個進(jìn)程或線程初始化和清除操作時,需要在相應(yīng)的DLL工程的.CPP文件中對DllMain()函數(shù)按照下面的格式書寫。<BR>>><BR>>><BR>BOOL
APIENTRY DllMain(HANDLE hModule,DWORD
ul_reason_for_call,LPVOID lpReserved)<BR>{<BR>switch(
ul_reason_for_call )<BR>{<BR>case
DLL_PROCESS_ATTACH:<BR>.......<BR>case
DLL_THREAD_ATTACH:<BR>.......<BR>case
DLL_THREAD_DETACH:<BR>.......<BR>case
DLL_PROCESS_DETACH:<BR>.......<BR>}<BR>return
TRUE;<BR>}<BR><BR>>>>>參數(shù)中,hMoudle是動態(tài)庫被調(diào)用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符);ul_reason_for_call是一個說明動態(tài)庫被調(diào)原因的標(biāo)志,當(dāng)進(jìn)程或線程裝入或卸載動態(tài)鏈接庫的時候,操作系統(tǒng)調(diào)用入口函數(shù),并說明動態(tài)鏈接庫被調(diào)用的原因,它所有的可能值為:DLL_PROCESS_ATTACH:
進(jìn)程被調(diào)用、DLL_THREAD_ATTACH: 線程被調(diào)用、DLL_PROCESS_DETACH:
進(jìn)程被停止、DLL_THREAD_DETACH:
線程被停止;lpReserved為保留參數(shù)。到此為止,DLL的入口函數(shù)已經(jīng)寫了,剩下部分的實現(xiàn)也不難,你可以在DLL工程中加入你所想要輸出的函數(shù)或變量了。<BR>>>>>我們已經(jīng)知道DLL是包含若干個函數(shù)的庫文件,應(yīng)用程序使用DLL中的函數(shù)之前,應(yīng)該先導(dǎo)出這些函數(shù),以便供給應(yīng)用程序使用。要導(dǎo)出這些函數(shù)有兩種方法,一是在定義函數(shù)時使用導(dǎo)出關(guān)鍵字_declspec(dllexport),另外一種方法是在創(chuàng)建DLL文件時使用模塊定義文件.Def。需要讀者注意的是在使用第一種方法的時候,不能使用DEF文件。下面通過兩個例子來說明如何使用這兩種方法創(chuàng)建DLL文件。<BR>>>>>1)使用導(dǎo)出函數(shù)關(guān)鍵字_declspec(dllexport)創(chuàng)建MyDll.dll,該動態(tài)鏈接庫中有兩個函數(shù),分別用來實現(xiàn)得到兩個數(shù)的最大和最小數(shù)。在MyDll.h和MyDLL.cpp文件中分別輸入如下原代碼:<BR>>><BR>//MyDLL.h<BR>extern
'C' _declspec(dllexport) int Max(int a, int
b);<BR>extern 'C' _declspec(dllexport) int Min(int a,
int
b);<BR>//MyDll.cpp<BR>#include<BR>#include'MyDll.h'<BR>int
Max(int a, int b)<BR>{<BR>if(a>=b)return
a;<BR>else<BR>return b;<BR>}<BR>int Min(int a, int
b)<BR>{<BR>if(a>=b)return b;<BR>else<BR>return
a;<BR>}<BR><BR>>>>>該動態(tài)鏈接庫編譯成功后,打開MyDll工程中的debug目錄,可以看到MyDll.dll、MyDll.lib兩個文件。LIB文件中包含DLL文件名和DLL文件中的函數(shù)名等,該LIB文件只是對應(yīng)該DLL文件的'映像文件',與DLL文件中,LIB文件的長度要小的多,在進(jìn)行隱式鏈接DLL時要用到它。讀者可能已經(jīng)注意到在MyDll.h中有關(guān)鍵字'extern
C',它可以使其他編程語言訪問你編寫的DLL中的函數(shù)。<BR>>>>>2)用.def文件創(chuàng)建工程MyDll<BR>>>>>為了用.def文件創(chuàng)建DLL,請先刪除上個例子創(chuàng)建的工程中的MyDll.h文件,保留MyDll.cpp并在該文件頭刪除#include
MyDll.h語句,同時往該工程中加入一個文本文件,命名為MyDll.def,再在該文件中加入如下代碼:<BR>LIBRARY
MyDll<BR>EXPORTS<BR>Max<BR>Min<BR>>>>>其中LIBRARY語句說明該def文件是屬于相應(yīng)DLL的,EXPORTS語句下列出要導(dǎo)出的函數(shù)名稱。我們可以在.def文件中的導(dǎo)出函數(shù)后加@n,如Max@1,Min@2,表示要導(dǎo)出的函數(shù)順序號,在進(jìn)行顯式連時可以用到它。該DLL編譯成功后,打開工程中的Debug目錄,同樣也會看到MyDll.dll和MyDll.lib文件。<BR>>>>>2.MFC
AppWizard[dll]方式生成常規(guī)/擴(kuò)展DLL<BR>>>>>在MFC
AppWizard[dll]下生成DLL文件又有三種方式,在創(chuàng)建DLL是,要根據(jù)實際情況選擇創(chuàng)建DLL的方式。一種是常規(guī)DLL靜態(tài)鏈接到MFC,另一種是常規(guī)DLL動態(tài)鏈接到MFC。兩者的區(qū)別是:前者使用的是MFC的靜態(tài)鏈接庫,生成的DLL文件長度大,一般不使用這種方式,后者使用MFC的動態(tài)鏈接庫,生成的DLL文件長度小;動態(tài)鏈接到MFC的規(guī)則DLL所有輸出的函數(shù)應(yīng)該以如下語句開始:
<BR>>><BR>AFX_MANAGE_STATE(AfxGetStaticModuleState(
))
//此語句用來正確地切換MFC模塊狀態(tài)<BR><BR>>>>>最后一種是MFC擴(kuò)展DLL,這種DLL特點是用來建立MFC的派生類,Dll只被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。前面我們已經(jīng)介紹過,Extension
DLLs 和Regular
DLLs不一樣,它沒有一個從CWinApp繼承而來的類的對象,編譯器默認(rèn)了一個DLL入口函數(shù)DLLMain()作為對DLL的初始化,你可以在此函數(shù)中實現(xiàn)初始化,代碼如下:<BR>>><BR>BOOL
WINAPI APIENTRY DLLMain(HINSTANCE hinstDll,DWORD reason
,LPVOID
flmpload)<BR>{<BR>switch(reason)<BR>{<BR>……………//初始化代碼;<BR>}<BR>return
true;<BR>}<BR><BR>>>>>參數(shù)hinstDll存放DLL的句柄,參數(shù)reason指明調(diào)用函數(shù)的原因,lpReserved是一個被系統(tǒng)所保留的參數(shù)。對于隱式鏈接是一個非零值,對于顯式鏈接值是零。<BR>>>>>在MFC下建立DLL文件,會自動生成def文件框架,其它與建立傳統(tǒng)的Non-MFC
DLL沒有什么區(qū)別,只要在相應(yīng)的頭文件寫入關(guān)鍵字_declspec(dllexport)函數(shù)類型和函數(shù)名等,或在生成的def文件中EXPORTS下輸入函數(shù)名就可以了。需要注意的是在向其它開發(fā)人員分發(fā)MFC擴(kuò)展DLL
時,不要忘記提供描述DLL中類的頭文件以及相應(yīng)的.LIB文件和DLL本身,此后開發(fā)人員就能充分利用你開發(fā)的擴(kuò)展DLL了。<BR>四、動態(tài)鏈接庫DLL的鏈接<BR>>>>>應(yīng)用程序使用DLL可以采用兩種方式:一種是隱式鏈接,另一種是顯式鏈接。在使用DLL之前首先要知道DLL中函數(shù)的結(jié)構(gòu)信息。Visual
C++6.0在VCin目錄下提供了一個名為Dumpbin.exe的小程序,用它可以查看DLL文件中的函數(shù)結(jié)構(gòu)。另外,Windows系統(tǒng)將遵循下面的搜索順序來定位DLL:
1.包含EXE文件的目錄,2.進(jìn)程的當(dāng)前工作目錄, 3.Windows系統(tǒng)目錄,
4.Windows目錄,5.列在Path環(huán)境變量中的一系列目錄。<BR>>>>>1.隱式鏈接<BR>>>>>隱式鏈接就是在程序開始執(zhí)行時就將DLL文件加載到應(yīng)用程序當(dāng)中。實現(xiàn)隱式鏈接很容易,只要將導(dǎo)入函數(shù)關(guān)鍵字_declspec(dllimport)函數(shù)名等寫到應(yīng)用程序相應(yīng)的頭文件中就可以了。下面的例子通過隱式鏈接調(diào)用MyDll.dll庫中的Min函數(shù)。首先生成一個項目為TestDll,在DllTest.h、DllTest.cpp文件中分別輸入如下代碼:<BR>>><BR>>><BR>//Dlltest.h<BR>#pragma
comment(lib,'MyDll.lib')<BR>extern
'C'_declspec(dllimport) int Max(int a,int b);<BR>extern
'C'_declspec(dllimport) int Min(int a,int
b);<BR>//TestDll.cpp<BR>#include<BR>#include'Dlltest.h'<BR>void
main()<BR>{int a;<BR>a=min(8,10)<BR>printf('比較的結(jié)果為%d
',a);<BR>}<BR>>><BR><BR>>>>>在創(chuàng)建DllTest.exe文件之前,要先將MyDll.dll和MyDll.lib拷貝到當(dāng)前工程所在的目錄下面,也可以拷貝到windows的System目錄下。如果DLL使用的是def文件,要刪除TestDll.h文件中關(guān)鍵字extern
'C'。TestDll.h文件中的關(guān)鍵字Progam commit是要Visual
C+的編譯器在link時,鏈接到MyDll.lib文件,當(dāng)然,開發(fā)人員也可以不使用#pragma
comment(lib,'MyDll.lib')語句,而直接在工程的Setting->Link頁的Object/Moduls欄填入MyDll.lib既可。<BR>>>>>2.顯式鏈接<BR>>>>>顯式鏈接是應(yīng)用程序在執(zhí)行過程中隨時可以加載DLL文件,也可以隨時卸載DLL文件,這是隱式鏈接所無法作到的,所以顯式鏈
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -