国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Visual C++中動態(tài)鏈接庫技術(shù)淺談

Visual C++中動態(tài)鏈接庫技術(shù)淺談

 引言

    較大的應(yīng)用程序都由很多模塊組成,這些模塊分別完成相對獨立的功能,它們彼此協(xié)作來完成整個軟件系統(tǒng)的工作。在構(gòu)造軟件系統(tǒng)時,如果將所有模塊的源代碼都靜態(tài)編譯到整個應(yīng)用程序的EXE文件中,會產(chǎn)生一些問題:一個缺點是增加了應(yīng)用程序的大小,它會占用更多的磁盤空間,程序運行時也會消耗較大的內(nèi)存空間,造成系統(tǒng)資源的浪費;另一個缺點是,在編寫大的EXE程序時,在每次修改重建時都必須調(diào)整編譯所有源代碼,增加了編譯過程的復(fù)雜性,也不利于階段性的單元測試;而且,一些模塊的功能可能較為通用,在構(gòu)造其它軟件系統(tǒng)時仍會被使用。

    Windows系統(tǒng)平臺上提供了一種完全不同的較有效的編程和運行環(huán)境,你可以將獨立的程序模塊創(chuàng)建為較小的動態(tài)鏈接庫(Dynamic Linkable Library,DLL)文件,并可對它們單獨編譯和測試。在運行時,只有當(dāng)EXE程序確實要調(diào)用這些DLL模塊的情況下,系統(tǒng)才會將它們裝載到內(nèi)存空間中。這種方式不僅減少了EXE文件的大小和對內(nèi)存空間的需求,而且使這些DLL模塊可以同時被多個應(yīng)用程序使用。

    動態(tài)鏈接庫概述

    動態(tài)鏈接庫技術(shù)是Windows最重要的實現(xiàn)技術(shù)之一,Windows的許多新功能、新特性都是通過DLL來實現(xiàn)的。其實,Windows本身就是由許多DLL組成的,它最基本的三大組成模塊Kernel、GDI和User都是DLL.

    一般來說,DLL是一種磁盤文件,以。dll、。DRV、。FON、。SYS和許多以。EXE為擴(kuò)展名的系統(tǒng)文件都可以是DLL.它由全局?jǐn)?shù)據(jù)、服務(wù)函數(shù)和資源組成,在運行時被系統(tǒng)加載到進(jìn)程的虛擬空間中,成為調(diào)用進(jìn)程的一部分。如果與其它DLL之間沒有沖突,該文件通常映射到進(jìn)程虛擬空間的同一地址上。DLL模塊中包含各種導(dǎo)出函數(shù),用于向外界提供服務(wù),Windows在加載DLL模塊時將進(jìn)程函數(shù)調(diào)用與DLL文件的導(dǎo)出函數(shù)相匹配。DLL可以有自己的數(shù)據(jù)段,但沒有自己的堆棧,DLL模塊需要的堆棧內(nèi)存都是從運行進(jìn)程的堆棧中分配出來的,使用與調(diào)用它的應(yīng)用程序相同的堆棧模式;一個DLL在內(nèi)存中只有一個實例;DLL實現(xiàn)了代碼封裝性;DLL的編制與具體的編程語言及編譯器無關(guān)。

    動態(tài)鏈接庫的分類

    微軟的Visual C++支持三種DLL,它們分別是Non-MFC Dll(非MFC動態(tài)庫)、Regular Dll(常規(guī)DLL)、Extension Dll(擴(kuò)展DLL)。

    1、Non-MFC DLL(非MFC動態(tài)庫)

    這種動態(tài)鏈接庫指的是不用MFC的類庫結(jié)構(gòu),直接用C語言寫的DLL,其導(dǎo)出的函數(shù)是標(biāo)準(zhǔn)的C接口,能被非MFC或MFC編寫的應(yīng)用程序所調(diào)用。如果建立的DLL不需要使用MFC,那么應(yīng)該建立Non-MFC DLL,因為使用MFC會增大用戶庫的大小,從而浪費用戶的磁盤和內(nèi)存空間。

    2、Regular DLL(常規(guī)DLL)

    這種動態(tài)鏈接庫和下述的Extension Dll一樣,是用MFC類庫編寫的,它的一個明顯的特點是在源文件里有一個繼承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)用程序,只要是能調(diào)用類C函數(shù)的應(yīng)用程序就可以,它們可以是在Visual C++、Delphi、Visual Basic、Borland C等編譯環(huán)境下利用DLL開發(fā)應(yīng)用程序。常規(guī)DLL又可細(xì)分成靜態(tài)鏈接到MFC和動態(tài)鏈接到MFC兩種:

    (1)靜態(tài)連接到MFC的動態(tài)連接庫只被VC的專業(yè)般和企業(yè)版所支持。該類DLL里的輸出函數(shù)可以被任意Win32程序使用,包括使用MFC的應(yīng)用程序。輸出函數(shù)有如下形式:

    extern "C" EXPORT YourExportedFunction( );

    如果沒有extern "C"修飾,輸出函數(shù)僅僅能從C++代碼中調(diào)用。
2)動態(tài)鏈接到MFC的常規(guī)DLL里的輸出函數(shù)可以被任意Win32程序使用,包括使用MFC的應(yīng)用程序。所有從DLL輸出的函數(shù)應(yīng)該以如下語句開始:

    AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

    此語句用來正確地切換MFC模塊狀態(tài)。

    3、Extension Dll(擴(kuò)展DLL)

    這種動態(tài)鏈接庫是使用MFC的動態(tài)鏈接版本所創(chuàng)建的,并且它只被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。例如你已經(jīng)創(chuàng)建了一個從MFC的CtoolBar類的派生類用于創(chuàng)建一個新的工具欄,為了導(dǎo)出這個類,你必須把它放到一個MFC擴(kuò)展的DLL中。擴(kuò)展DLL 和常規(guī)DLL不一樣,它沒有一個從CWinApp繼承而來的類的對象,所以,開發(fā)人員必須在DLL中的DllMain函數(shù)添加初始化代碼和結(jié)束代碼。與常規(guī)DLL相比,擴(kuò)展的DLL有如下不同點:

    1) 它沒有一個從CWinApp派生的對象;

    2) 它必須有一個DLLMain函數(shù);

    3) DLLMain調(diào)用AfxInitExtensionModule函數(shù),必須檢查該函數(shù)的返回值,如果返回0,DLLMmain也返回0;

    4) 如果它希望輸出CRuntimeClass類型的對象或者資源(Resources),則需要提供一個初始化函數(shù)來創(chuàng)建一個CDynLinkLibrary對象。并且,有必要把初始化函數(shù)輸出;

    5) 使用擴(kuò)展DLL的MFC應(yīng)用程序必須有一個從CWinApp派生的類,而且,一般在InitInstance里調(diào)用擴(kuò)展DLL的初始化函數(shù)。

    動態(tài)連接庫的建立

    1、Non-MFC DLL的建立

    每一個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ù)按照下面的格式書寫。

 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
}
return TRUE;
}

 

    參數(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)用的原因,它所有的可能值為:

    (1)DLL_PROCESS_ATTACH: 進(jìn)程被調(diào)用或調(diào)用Load Library,DLL被鏈接到當(dāng)前進(jìn)程的地址空間并被初始化;

    (2)DLL_THREAD_ATTACH: 當(dāng)前進(jìn)程創(chuàng)建一個新線程,DLL在新線程正文內(nèi)被調(diào)用;

    (3)DLL_PROCESS_DETACH: 調(diào)用DLL的進(jìn)程被終止,DLL被卸載;

    (4)DLL_THREAD_DETACH: 調(diào)用DLL的線程被終止,DLL被卸載;

    lpReserved為保留參數(shù)。

    如果在DLL中加入想要輸出的函數(shù)、變量、C++類或其它函數(shù),可以調(diào)用VC的關(guān)鍵字_declspec(dllexport)。

    2、MFC AppWizard[dll]方式下Regular DLL和Extension DLL的建立

    在MFC AppWizard[dll]下生成的DLL文件有三種方式:靜態(tài)鏈接到MFC的常規(guī)DLL、動態(tài)鏈接到MFC的常規(guī)DLL以及MFC擴(kuò)展DLL,在創(chuàng)建DLL是,要根據(jù)實際情況選擇創(chuàng)建DLL的方式。

    靜態(tài)鏈接到MFC的常規(guī)DLL和靜態(tài)連接到MFC常規(guī)DLL的區(qū)別是:前者使用的是MFC的靜態(tài)鏈接庫,生成的DLL文件長度大,一般不使用這種方式;后者使用MFC的動態(tài)鏈接庫,生成的DLL文件長度??;動態(tài)鏈接到MFC的常規(guī)DLL所有輸出的函數(shù)應(yīng)該以如下語句開始:

    AFX_MANAGE_STATE(AfxGetStaticModuleState( )) //此語句用來正確地切換MFC模塊狀態(tài)

    MFC擴(kuò)展DLL的特點是用來建立MFC的派生類,Dll只被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。Extension DLLs 和Regular DLLs不一樣,它沒有一個從CWinApp繼承而來的類的對象,編譯器默認(rèn)了一個DLL入口函數(shù)DLLMain()作為對DLL的初始化,你可以在此函數(shù)中實現(xiàn)初始化,代碼如下:

 

 

 BOOL WINAPI APIENTRY DLLMain(HINSTANCE hinstDll,DWORD reason ,LPVOID flmpload)
{
switch(reason)
{
……………//初始化代碼;
}
return true;
}

    參數(shù)hinstDll存放DLL的句柄,參數(shù)reason指明調(diào)用函數(shù)的原因,lpReserved是一個被系統(tǒng)所保留的參數(shù)。對于隱式鏈接是一個非零值,對于顯式鏈接值是零。

 

    動態(tài)連接庫的調(diào)用

    動態(tài)鏈接庫的調(diào)用可以分為兩種:一種是隱式調(diào)用,一種是顯示調(diào)用。

    1、隱式的調(diào)用

    這種調(diào)用方式需要把產(chǎn)生動態(tài)連接庫時產(chǎn)生的。LIB文件加入到應(yīng)用程序的工程中,在使用DLL中的函數(shù)時,只須說明一下后就可以直接通過函數(shù)名調(diào)用DLL的輸出函數(shù),調(diào)用方法和程序內(nèi)部其他的函數(shù)是一樣的。隱式調(diào)用不需要調(diào)用Load Library()和Free Library()。程序員在建立一個DLL文件時,鏈接程序會自動生成一個與之對應(yīng)的LIB導(dǎo)入文件。該文件包含了每一個DLL導(dǎo)出函數(shù)的符號名和可選的標(biāo)識號,但是并不含有實際的代碼。LIB文件作為DLL的替代文件被編譯到應(yīng)用程序項目中。

    當(dāng)程序員通過隱式調(diào)用方式編譯生成應(yīng)用程序時,應(yīng)用程序中的調(diào)用函數(shù)與LIB文件中導(dǎo)出符號相匹配,這些符號或標(biāo)識號被寫入到生成的EXE文件中。LIB文件中也包含了對應(yīng)的DLL文件名(但不是完全的路徑名),鏈接程序也將其存儲在EXE文件內(nèi)部。當(dāng)應(yīng)用程序運行過程中需要加載DLL文件時,Windows根據(jù)這些信息發(fā)現(xiàn)并加載DLL,然后通過符號名或標(biāo)識號實現(xiàn)對DLL函數(shù)的動態(tài)鏈接。所有被應(yīng)用程序調(diào)用的DLL文件都會在應(yīng)用程序EXE文件加載時被加載在到內(nèi)存中。

    2、顯式調(diào)用

    這種調(diào)用方式是指在應(yīng)用程序中用Load Library或MFC提供的AfxLoadLibrary顯式的將自己所做的動態(tài)連接庫調(diào)進(jìn)來,并指定DLL的路徑作為參數(shù)。LoadLibary返回HINSTANCE參數(shù),應(yīng)用程序在調(diào)用GetProcAddress函數(shù)時使用這一參數(shù)。當(dāng)完成對動態(tài)鏈接庫的導(dǎo)入以后,再使用GetProcAddress()獲取想要引入的函數(shù),該函數(shù)將符號名或標(biāo)識號轉(zhuǎn)換為DLL內(nèi)部的地址,之后就可以象使用本應(yīng)用程序自定義的函數(shù)一樣來調(diào)用此引入函數(shù)了。在應(yīng)用程序退出之前,應(yīng)該用Free Library或MFC提供的AfxFreeLibrary釋放動態(tài)連接庫。

    使用顯式調(diào)用方式可以讓程序員來決定DLL文件何時加載或不加載,而操作系統(tǒng)在載入應(yīng)用程序時不必要將所有該應(yīng)用程序所引用的DLL都一起加載到內(nèi)存中,只要在使用某個DLL時再將其載入,這樣就可以減少應(yīng)用程序在初始加載時所使用的時間和對內(nèi)存的消耗。在對DLL加載的過程中,Windows將遵循下面的搜索順序來定位DLL:

    ①包含EXE文件的目錄;

    ②進(jìn)程的當(dāng)前工作目錄 ;

    ③Windows系統(tǒng)目錄 ;

    ④Windows目錄 ;

    ⑤列在Path環(huán)境變量中的一系列目錄。

    總結(jié)

    在Windows操作系統(tǒng)中使用動態(tài)鏈接庫(DLL)有很多優(yōu)點,最主要的一點是多個應(yīng)用程序、甚至是不同語言編寫的應(yīng)用程序可以共享一個DLL文件,真正實現(xiàn)了資源"共享",大大縮小了應(yīng)用程序的執(zhí)行代碼,更加有效地利用了內(nèi)存;使用DLL的另一個優(yōu)點是DLL文件作為一個單獨的程序模塊,封裝性、獨立性好,在軟件需要升級的時候,開發(fā)人員只需要修改相應(yīng)的DLL文件就可以了,而且,當(dāng)DLL中的函數(shù)改變后,如果沒有修改參數(shù),程序代碼并不需要重新編譯。這在編程時十分有用,大大提高了軟件開發(fā)和維護(hù)的效率。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
動態(tài)鏈接庫創(chuàng)建與使用
VC++動態(tài)鏈接庫編程總結(jié)一
動態(tài)鏈接庫DLL編程(一)之簡介
vc dll編程
DLL(Dynamic Link Libraries)
使用c 開發(fā)excel插件 (第3章動態(tài)鏈接庫(dynamic
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服