




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C+Dll編寫入門(轉(zhuǎn)載)收藏一、前言自從微軟推出16位的Windows操作系統(tǒng)起,此后每種版本的Windows操作系統(tǒng)都非常依賴于動(dòng)態(tài)鏈接庫(DLL)中的函數(shù)和數(shù)據(jù),實(shí)際上Windows操作系統(tǒng)中幾乎所有的內(nèi)容都由DLL以一種或另外一種形式代表著,例如顯示的字體和圖標(biāo)存儲(chǔ)在GDIDLL中、顯示W(wǎng)indows桌面和處理用戶的輸入所需要的代碼被存儲(chǔ)在一個(gè)UserDLL中、Windows編程所需要的大量的API函數(shù)也被包含在KernelDLL中。在Windows操作系統(tǒng)中使用DLL有很多優(yōu)點(diǎn),最主要的一點(diǎn)是多個(gè)應(yīng)用程序、甚至是不同語言編寫的應(yīng)用程序可以共享一個(gè)DLL文件,真正實(shí)現(xiàn)了資源共享,大大縮
2、小了應(yīng)用程序的執(zhí)行代碼,更加有效的利用了內(nèi)存;使用DLL的另一個(gè)優(yōu)點(diǎn)是DLL文件作為一個(gè)單獨(dú)的程序模塊,封裝性、獨(dú)立性好,在軟件需要升級(jí)的時(shí)候,開發(fā)人員只需要修改相應(yīng)的DLL文件就可以了,而且,當(dāng)DLL中的函數(shù)改變后,只要不是參數(shù)的改變,程序代碼并不需要重新編譯。這在編程時(shí)十分有用,大大提高了軟件開發(fā)和維護(hù)的效率。既然DLL那么重要,所以搞清楚什么是DLL、如何在Windows操作系統(tǒng)中開發(fā)使用DLL是程序開發(fā)人員不得不解決的一個(gè)問題。本文針對(duì)這些問題,通過一個(gè)簡(jiǎn)單的例子,即在一個(gè)DLL中實(shí)現(xiàn)比較最大、最小整數(shù)這兩個(gè)簡(jiǎn)單函數(shù),全面地解析了在VisualC+編譯環(huán)境下編程實(shí)現(xiàn)DLL的過程,文章中
3、所用到的程序代碼在Windows98系統(tǒng)、VisualC+6.0編譯環(huán)境下通過。二、DLL的概念DLL是建立在客戶/服務(wù)器通信的概念上,包含若干函數(shù)、類或資源的庫文件,函數(shù)和數(shù)據(jù)被存儲(chǔ)在一個(gè)DLL(服務(wù)器)上并由一個(gè)或多個(gè)客戶導(dǎo)出而使用,這些客戶可以是應(yīng)用程序或者是其它的DLL。DLL庫不同于靜態(tài)庫,在靜態(tài)庫情況下,函數(shù)和數(shù)據(jù)被編譯進(jìn)一個(gè)二進(jìn)制文件(通常擴(kuò)展名為*丄IB),VisualC+的編譯器在處理程序代碼時(shí)將從靜態(tài)庫中恢復(fù)這些函數(shù)和數(shù)據(jù)并把他們和應(yīng)用程序中的其他模塊組合在一起生成可執(zhí)行文件。這個(gè)過程稱為靜態(tài)鏈接,此時(shí)因?yàn)閼?yīng)用程序所需的全部?jī)?nèi)容都是從庫中復(fù)制了出來,所以靜態(tài)庫本身并不需要與
4、可執(zhí)行文件一起發(fā)行。在動(dòng)態(tài)庫的情況下,有兩個(gè)文件,一個(gè)是引入庫(丄IB)文件,一個(gè)是DLL文件,引入庫文件包含被DLL導(dǎo)出的函數(shù)的名稱和位置,DLL包含實(shí)際的函數(shù)和數(shù)據(jù),應(yīng)用程序使用LIB文件鏈接到所需要使用的DLL文件,庫中的函數(shù)和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件中,因此在應(yīng)用程序的可執(zhí)行文件中,存放的不是被調(diào)用的函數(shù)代碼,而是DLL中所要調(diào)用的函數(shù)的內(nèi)存地址,這樣當(dāng)一個(gè)或多個(gè)應(yīng)用程序運(yùn)行是再把程序代碼和被調(diào)用的函數(shù)代碼鏈接起來,從而節(jié)省了內(nèi)存資源。從上面的說明可以看出,DLL和丄IB文件必須隨應(yīng)用程序一起發(fā)行,否則應(yīng)用程序?qū)?huì)產(chǎn)生錯(cuò)誤。微軟的VisualC+支持三種DLL,它們分別是Non-MFC
5、Dll(非MFC動(dòng)態(tài)庫)、RegularDll(常規(guī)DLL)、ExtensionDll(擴(kuò)展DLL)。Non-MFCDLL指的是不用MFC的類庫結(jié)構(gòu),直接用C語言寫的DLL,其導(dǎo)出的函數(shù)是標(biāo)準(zhǔn)的C接口,能被非MFC或MFC編寫的應(yīng)用程序所調(diào)用。RegularDLL:和下述的ExtensionDlls一樣,是用MFC類庫編寫的,它的一個(gè)明顯的特點(diǎn)是在源文件里有一個(gè)繼承CWinApp的類(注意:此類DLL雖然從CWinApp派生,但沒有消息循環(huán)),被導(dǎo)出的函數(shù)是C函數(shù)、C+類或者C+成員函數(shù)(注意不要把術(shù)語C+類與MFC的微軟基礎(chǔ)C+類相混淆),調(diào)用常規(guī)DLL的應(yīng)用程序不必是MFC應(yīng)用程序,只要是
6、能調(diào)用類C函數(shù)的應(yīng)用程序就可以,它們可以是在VisualC+、Dephi、VisualBasiGBorlandC等編譯環(huán)境下利用DLL開發(fā)應(yīng)用程序。常規(guī)DLL又可細(xì)分成靜態(tài)鏈接到MFC和動(dòng)態(tài)鏈接到MFC上的,這兩種常規(guī)DLL的區(qū)別將在下面介紹。與常規(guī)DLL相比,使用擴(kuò)展DLL用于導(dǎo)出增強(qiáng)MFC基礎(chǔ)類的函數(shù)或子類,用這種類型的動(dòng)態(tài)鏈接庫,可以用來輸出一個(gè)從MFC所繼承下來的類。擴(kuò)展DLL是使用MFC的動(dòng)態(tài)鏈接版本所創(chuàng)建的,并且它只被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。例如你已經(jīng)創(chuàng)建了一個(gè)從MFC的CtoolBar類的派生類用于創(chuàng)建一個(gè)新的工具欄,為了導(dǎo)出這個(gè)類,你必須把它放到一個(gè)MFC擴(kuò)展的DL
7、L中。擴(kuò)展DLL和常規(guī)DLL不一樣,它沒有一個(gè)從CWinApp繼承而來的類的對(duì)象,所以,開發(fā)人員必須在DLL中的DllMain函數(shù)添加初始化代碼和結(jié)束代碼。三、動(dòng)態(tài)鏈接庫的創(chuàng)建在VisualC+6.0開發(fā)環(huán)境下,打開FileNewProject選項(xiàng),可以選擇Win32Dynamic-LinkLibrary或MFCAppWizarddll來以不同的方式來創(chuàng)建Non-MFCDll、RegularDll、ExtensionDll等不同種類的動(dòng)態(tài)鏈接庫。1.Win32Dynamic-LinkLibrary方式創(chuàng)建Non-MFCDLL動(dòng)態(tài)鏈接庫每一個(gè)DLL必須有一個(gè)入口點(diǎn),這就象我們用C編寫的應(yīng)用程序一
8、樣,必須有一個(gè)WINMAIN函數(shù)一樣。在Non-MFCDLL中DllMain是一個(gè)缺省的入口函數(shù),你不需要編寫自己的DLL入口函數(shù),用這個(gè)缺省的入口函數(shù)就能使動(dòng)態(tài)鏈接庫被調(diào)用時(shí)得到正確的初始化。如果應(yīng)用程序的DLL需要分配額外的內(nèi)存或資源時(shí),或者說需要對(duì)每個(gè)進(jìn)程或線程初始化和清除操作時(shí),需要在相應(yīng)的DLL工程的.CPP文件中對(duì)DllMain()函數(shù)按照下面的格式書寫。BOOLAPIENTRYDllMain(HANDLEhModule,DWORDul_reason_for_call,LPVOIDlpReserved)switch(ul_reason_for_call)caseDLL_PROCES
9、S_ATTACH:caseDLL_THREAD_ATTACH:caseDLL_THREAD_DETACH:caseDLL_PROCESS_DETACH:returnTRUE;參數(shù)中,hMoudle是動(dòng)態(tài)庫被調(diào)用時(shí)所傳遞來的一個(gè)指向自己的句柄(實(shí)際上,它是指向_DGROUP段的一個(gè)選擇符);ul_reason_for_call是一個(gè)說明動(dòng)態(tài)庫被調(diào)原因的標(biāo)志,當(dāng)進(jìn)程或線程裝入或卸載動(dòng)態(tài)鏈接庫的時(shí)候,操作系統(tǒng)調(diào)用入口函數(shù),并說明動(dòng)態(tài)鏈接庫被調(diào)用的原因,它所有的可能值為:DLL_PROCESS_ATTACH:進(jìn)程被調(diào)用、DLL_THREAD_ATTACH:線程被調(diào)用、DLL_PROCESS_DETAC
10、H:進(jìn)程被停止、DLL_THREAD_DETACH:線程被停止;IpReserved為保留參數(shù)。到此為止,DLL的入口函數(shù)已經(jīng)寫了,剩下部分的實(shí)現(xiàn)也不難,你可以在DLL工程中加入你所想要輸出的函數(shù)或變量了。我們已經(jīng)知道DLL是包含若干個(gè)函數(shù)的庫文件,應(yīng)用程序使用DLL中的函數(shù)之前,應(yīng)該先導(dǎo)出這些函數(shù),以便供給應(yīng)用程序使用。要導(dǎo)出這些函數(shù)有兩種方法,一是在定義函數(shù)時(shí)使用導(dǎo)出關(guān)鍵字_declspec(dllexport),另外一種方法是在創(chuàng)建DLL文件時(shí)使用模塊定義文件.Def。需要讀者注意的是在使用第一種方法的時(shí)候,不能使用DEF文件。下面通過兩個(gè)例子來說明如何使用這兩種方法創(chuàng)建DLL文件。1)
11、使用導(dǎo)出函數(shù)關(guān)鍵字_declspec(dllexport)創(chuàng)建MyDll.dll,該動(dòng)態(tài)鏈接庫中有兩個(gè)函數(shù),分別用來實(shí)現(xiàn)得到兩個(gè)數(shù)的最大和最小數(shù)。在MyDll.h和MyDLL.cpp文件中分別輸入如下原代碼:/MyDLL.hexternC_declspec(dllexport)intMax(inta,intb);externC_declspec(dllexport)intMin(inta,intb);/MyDll.cpp#include#includeMyDll.hintMax(inta,intb)if(a=b)returna;elsereturnb;intMin(inta,intb)if(a
12、=b)returnb;elsereturna;該動(dòng)態(tài)鏈接庫編譯成功后,打開MyDll工程中的debug目錄,可以看到MyDll.dll、MyDll.lib兩個(gè)文件。LIB文件中包含DLL文件名和DLL文件中的函數(shù)名等,該LIB文件只是對(duì)應(yīng)該DLL文件的映像文件,與DLL文件中,LIB文件的長(zhǎng)度要小的多,在進(jìn)行隱式鏈接DLL時(shí)要用到它。讀者可能已經(jīng)注意到在MyDll.h中有關(guān)鍵字externC,它可以使其他編程語言訪問你編寫的DLL中的函數(shù)。2)用.def文件創(chuàng)建工程MyDll為了用.def文件創(chuàng)建DLL,請(qǐng)先刪除上個(gè)例子創(chuàng)建的工程中的MyDll.h文件,保留MyDll.cpp并在該文件頭刪除#
13、includeMyDll.h語句,同時(shí)往該工程中加入一個(gè)文本文件,命名為MyDll.def,再在該文件中加入如下代碼:LIBRARYMyDll注意這里的MyDll是工程名如果不同則應(yīng)用程序連接庫時(shí)會(huì)發(fā)生連接錯(cuò)誤EXPORTSMax1,Min2,其中LIBRARY語句說明該def文件是屬于相應(yīng)DLL的,EXPORTS語句下列出要導(dǎo)出的函數(shù)名稱。我們可以在.def文件中的導(dǎo)出函數(shù)后加n,如Max1,Min2,表示要導(dǎo)出的函數(shù)順序號(hào),在進(jìn)行顯式連時(shí)可以用到它。該DLL編譯成功后,打開工程中的Debug目錄,同樣也會(huì)看到MyDll.dll和MyDll.lib文件。2.MFCAppWizarddll方式
14、生成常規(guī)/擴(kuò)展DLL在MFCAppWizarddll下生成DLL文件又有三種方式,在創(chuàng)建DLL是,要根據(jù)實(shí)際情況選擇創(chuàng)建DLL的方式。一種是常規(guī)DLL靜態(tài)鏈接到MFC,另一種是常規(guī)DLL動(dòng)態(tài)鏈接到MFC。兩者的區(qū)別是:前者使用的是MFC的靜態(tài)鏈接庫,生成的DLL文件長(zhǎng)度大,一般不使用這種方式,后者使用MFC的動(dòng)態(tài)鏈接庫,生成的DLL文件長(zhǎng)度??;動(dòng)態(tài)鏈接到MFC的規(guī)則DLL所有輸出的函數(shù)應(yīng)該以如下語句開始:AFX_MANAGE_STATE(AfxGetStaticModuleState()/此語句用來正確地切換MFC模塊狀態(tài)最后一種是MFC擴(kuò)展DLL,這種DLL特點(diǎn)是用來建立MFC的派生類,DI
15、I只被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。前面我們已經(jīng)介紹過,ExtensionDLLs和RegularDLLs不一樣,它沒有一個(gè)從CWinApp繼承而來的類的對(duì)象,編譯器默認(rèn)了一個(gè)DLL入口函數(shù)DLLMain()作為對(duì)DLL的初始化,你可以在此函數(shù)中實(shí)現(xiàn)初始化,代碼如下:BOOLWINAPIAPIENTRYDLLMain(HINSTANCEhinstDll,DWORDreason,LPVOIDflmpload)switch(reason)初/始化代碼;returntrue;參數(shù)hinstDII存放DLL的句柄,參數(shù)reason指明調(diào)用函數(shù)的原因,IpReserved是一個(gè)被系統(tǒng)所保留的參數(shù)。
16、對(duì)于隱式鏈接是一個(gè)非零值,對(duì)于顯式鏈接值是零。在MFC下建立DLL文件,會(huì)自動(dòng)生成def文件框架,其它與建立傳統(tǒng)的Non-MFCDLL沒有什么區(qū)別,只要在相應(yīng)的頭文件寫入關(guān)鍵字_declspec(dllexport)函數(shù)類型和函數(shù)名等,或在生成的def文件中EXPORTS下輸入函數(shù)名就可以了。需要注意的是在向其它開發(fā)人員分發(fā)MFC擴(kuò)展DLL時(shí),不要忘記提供描述DLL中類的頭文件以及相應(yīng)的丄IB文件和DLL本身,此后開發(fā)人員就能充分利用你開發(fā)的擴(kuò)展DLL了。四、動(dòng)態(tài)鏈接庫DLL的鏈接應(yīng)用程序使用DLL可以采用兩種方式:一種是隱式鏈接,另一種是顯式鏈接。在使用DLL之前首先要知道DLL中函數(shù)的結(jié)構(gòu)
17、信息oVisualC+6.0在VCbin目錄下提供了一個(gè)名為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)境變量中的一系列目錄。1.隱式鏈接隱式鏈接就是在程序開始執(zhí)行時(shí)就將DLL文件加載到應(yīng)用程序當(dāng)中。實(shí)現(xiàn)隱式鏈接很容易,只要將導(dǎo)入函數(shù)關(guān)鍵字_declspec(dllimport)函數(shù)名等寫到應(yīng)用程序相應(yīng)的頭文件中就可以了。下面的例子通過隱式鏈接調(diào)用MyDll.dll庫中的Min函數(shù)。首先生成一個(gè)
18、項(xiàng)目為TestDll,在DIITest.h、DllTest.cpp文件中分別輸入如下代碼:/Dlltest.h#pragmacomment(lib,MyDll.lib)externC_declspec(dllimport)intMax(inta,intb);externC_declspec(dllimport)intMin(inta,intb);/TestDll.cpp#include#includeDlltest.hvoidmain()inta;a=min(8,10)printf(比較的結(jié)果為%dn,a);注意如果程序發(fā)生連接錯(cuò)誤則要把lib文件加要工程里去在創(chuàng)建DIITest.exe文件之
19、前,要先將MyDll.dlI和MyDll.lib拷貝到當(dāng)前工程所在的目錄下面,也可以拷貝到windows的System目錄下。如果DLL使用的是def文件,要?jiǎng)h除TestDll.h文件中關(guān)鍵字externC。TestDll.h文件中的關(guān)鍵字Progamcommit是要VisualC+的編譯器在link時(shí),鏈接到MyDll.lib文件,當(dāng)然,開發(fā)人員也可以不使用#卩agmacomment(lib,MyDll.lib)語句,而直接在工程的Setting-Link頁的Object/Moduls欄填入MyDll.lib既可。2顯式鏈接顯式鏈接是應(yīng)用程序在執(zhí)行過程中隨時(shí)可以加載DLL文件,也可以隨時(shí)卸載
20、DLL文件,這是隱式鏈接所無法作到的,所以顯式鏈接具有更好的靈活性,對(duì)于解釋性語言更為合適。不過實(shí)現(xiàn)顯式鏈接要麻煩一些。在應(yīng)用程序中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動(dòng)態(tài)鏈接庫調(diào)進(jìn)來,動(dòng)態(tài)鏈接庫的文件名即是上述兩個(gè)函數(shù)的參數(shù),此后再用GetProcAddress()獲取想要引入的函數(shù)。自此,你就可以象使用如同在應(yīng)用程序自定義的函數(shù)一樣來調(diào)用此引入函數(shù)了。在應(yīng)用程序退出之前,應(yīng)該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動(dòng)態(tài)鏈接庫。下面是通過顯式鏈接調(diào)用DLL中的Max函數(shù)的例子。#include#includevoidmain(void)typedefint(*pMax)(inta,intb);typedefint(*pMin)(inta,intb);HINSTANCEhDLL;PMaxMaxHDLL=LoadLibrary
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度智能倉儲(chǔ)管理合同訂單及出貨評(píng)審表模板
- 2025年度認(rèn)繳制跨境電商股權(quán)轉(zhuǎn)讓協(xié)議書
- 二零二五年度機(jī)械維修工程師用工協(xié)議
- 2025年度高速公路施工場(chǎng)地借用安全責(zé)任協(xié)議
- 2025年度租賃房屋維修免責(zé)服務(wù)協(xié)議
- 2025年度訂單小麥?zhǔn)召?gòu)綠色種植合作協(xié)議
- 二零二五年度風(fēng)電場(chǎng)運(yùn)維勞務(wù)承攬合同
- 第12課 從明朝建立到清軍入關(guān) 教學(xué)設(shè)計(jì)-2024-2025學(xué)年高一歷史統(tǒng)編版(2019)必修中外歷史綱要上冊(cè)
- 二零二五年度人氣主播形象授權(quán)合同
- 二零二五年度民事糾紛法律委托代理協(xié)議
- 餐飲及食品安全管理制度
- 2025年安徽電氣工程職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫及答案1套
- 2025年房屋交易代持策劃協(xié)議書
- 課題申報(bào)參考:“四新”建設(shè)背景下教育創(chuàng)新與課程數(shù)字化實(shí)踐研究
- 2025年上半年贛州市于都縣招聘城管協(xié)管員易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年煙臺(tái)汽車工程職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試近5年??及鎱⒖碱}庫含答案解析
- 2025年江蘇農(nóng)牧科技職業(yè)學(xué)院高職單招職業(yè)技能測(cè)試近5年??及鎱⒖碱}庫含答案解析
- 2024年廣東省《輔警招聘考試必刷500題》考試題庫及答案【易錯(cuò)題】
- 中考數(shù)學(xué)總復(fù)習(xí)第一章第3課時(shí)二次根式課件
- 天然氣脫硫完整版本
- 2025年中國(guó)電子煙行業(yè)發(fā)展前景與投資戰(zhàn)略規(guī)劃分析報(bào)告
評(píng)論
0/150
提交評(píng)論