青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

醬壇子

專注C++技術(shù) 在這里寫下自己的學(xué)習(xí)心得 感悟 和大家討論 共同進(jìn)步(歡迎批評(píng)!?。。?/p>

  C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
  66 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

公告

王一偉 湖南商學(xué)院畢業(yè) 電子信息工程專業(yè)

常用鏈接

留言簿(19)

我參與的團(tuán)隊(duì)

搜索

  •  

積分與排名

  • 積分 - 390121
  • 排名 - 64

最新隨筆

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

DLL(Dynamic Link Libraries)專題:

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

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

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

??? 在Win32環(huán)境中,每個(gè)進(jìn)程都復(fù)制了自己的讀/寫全局變量。如果想要與其它進(jìn)程共享內(nèi)存,必須使用內(nèi)存映射文件或者聲明一個(gè)共享數(shù)據(jù)段。DLL模塊需要的堆棧內(nèi)存都是從運(yùn)行進(jìn)程的堆棧中分配出來(lái)的。Windows在加載DLL模塊時(shí)將進(jìn)程函數(shù)調(diào)用與DLL文件的導(dǎo)出函數(shù)相匹配。Windows操作系統(tǒng)對(duì)DLL的操作僅僅是把DLL映射到需要它的進(jìn)程的虛擬地址空間里去。DLL函數(shù)中的代碼所創(chuàng)建的任何對(duì)象(包括變量)都?xì)w調(diào)用它的線程或進(jìn)程所有.???????

一、關(guān)于調(diào)用方式:

1、靜態(tài)調(diào)用方式:由編譯系統(tǒng)完成對(duì)DLL的加載和應(yīng)用程序結(jié)束時(shí)DLL卸載的編碼(如還有其它程序使用該DLL,則Windows對(duì)DLL的應(yīng)用記錄減1,直到所有相關(guān)程序都結(jié)束對(duì)該DLL的使用時(shí)才釋放它),簡(jiǎn)單實(shí)用,但不夠靈活,只能滿足一般要求。

?隱式的調(diào)用:需要把產(chǎn)生動(dòng)態(tài)連接庫(kù)時(shí)產(chǎn)生的.LIB文件加入到應(yīng)用程序的工程中,想使用DLL中的函數(shù)時(shí),只須說(shuō)明一下。隱式調(diào)用不需要調(diào)用LoadLibrary()和FreeLibrary()。程序員在建立一個(gè)DLL文件時(shí),鏈接程序會(huì)自動(dòng)生成一個(gè)與之對(duì)應(yīng)的LIB導(dǎo)入文件。該文件包含了每一個(gè)DLL導(dǎo)出函數(shù)的符號(hào)名和可選的標(biāo)識(shí)號(hào),但是并不含有實(shí)際的代碼。LIB文件作為DLL的替代文件被編譯到應(yīng)用程序項(xiàng)目中。當(dāng)程序員通過(guò)靜態(tài)鏈接方式編譯生成應(yīng)用程序時(shí),應(yīng)用程序中的調(diào)用函數(shù)與LIB文件中導(dǎo)出符號(hào)相匹配,這些符號(hào)或標(biāo)識(shí)號(hào)進(jìn)入到生成的EXE文件中。LIB文件中也包含了對(duì)應(yīng)的DLL文件名(但不是完全的路徑名),鏈接程序?qū)⑵浯鎯?chǔ)在EXE文件內(nèi)部。當(dāng)應(yīng)用程序運(yùn)行過(guò)程中需要加載DLL文件時(shí),Windows根據(jù)這些信息發(fā)現(xiàn)并加載DLL,然后通過(guò)符號(hào)名或標(biāo)識(shí)號(hào)實(shí)現(xiàn)對(duì)DLL函數(shù)的動(dòng)態(tài)鏈接。所有被應(yīng)用程序調(diào)用的DLL文件都會(huì)在應(yīng)用程序EXE文件加載時(shí)被加載在到內(nèi)存中。可執(zhí)行程序鏈接到一個(gè)包含DLL輸出函數(shù)信息的輸入庫(kù)文件(.LIB文件)。操作系統(tǒng)在加載使用可執(zhí)行程序時(shí)加載DLL??蓤?zhí)行程序直接通過(guò)函數(shù)名調(diào)用DLL的輸出函數(shù),調(diào)用方法和程序內(nèi)部其他的函數(shù)是一樣的。


2、動(dòng)態(tài)調(diào)用方式:是由編程者用API函數(shù)加載和卸載DLL來(lái)達(dá)到調(diào)用DLL的目的,使用上較復(fù)雜,但能更加有效地使用內(nèi)存,是編制大型應(yīng)用程序時(shí)的重要方式。

?顯式的調(diào)用:是指在應(yīng)用程序中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動(dòng)態(tài)連接庫(kù)調(diào)進(jìn)來(lái),動(dòng)態(tài)連接庫(kù)的文件名即是上面兩個(gè)函數(shù)的參數(shù),再用GetProcAddress()獲取想要引入的函數(shù)。自此,你就可以象使用如同本應(yīng)用程序自定義的函數(shù)一樣來(lái)調(diào)用此引入函數(shù)了。在應(yīng)用程序退出之前,應(yīng)該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動(dòng)態(tài)連接庫(kù)。直接調(diào)用Win32 的LoadLibary函數(shù),并指定DLL的路徑作為參數(shù)。LoadLibary返回HINSTANCE參數(shù),應(yīng)用程序在調(diào)用GetProcAddress函數(shù)時(shí)使用這一參數(shù)。GetProcAddress函數(shù)將符號(hào)名或標(biāo)識(shí)號(hào)轉(zhuǎn)換為DLL內(nèi)部的地址。程序員可以決定DLL文件何時(shí)加載或不加載,顯式鏈接在運(yùn)行時(shí)決定加載哪個(gè)DLL文件。使用DLL的程序在使用之前必須加載(LoadLibrary)加載DLL從而得到一個(gè)DLL模塊的句柄,然后調(diào)用GetProcAddress函數(shù)得到輸出函數(shù)的指針,在退出之前必須卸載DLL(FreeLibrary)。

??? Windows將遵循下面的搜索順序來(lái)定位DLL:
1.包含EXE文件的目錄,
2.進(jìn)程的當(dāng)前工作目錄,
3.Windows系統(tǒng)目錄,
4.Windows目錄,
5.列在Path環(huán)境變量中的一系列目錄。

二、MFC中的dll:

a、Non-MFC DLL:指的是不用MFC的類庫(kù)結(jié)構(gòu),直接用C語(yǔ)言寫的DLL,其輸出的函數(shù)一般用的是標(biāo)準(zhǔn)C接口,并能被非MFC或MFC編寫的應(yīng)用程序所調(diào)用。

b、Regular DLL:和下述的Extension Dlls一樣,是用MFC類庫(kù)編寫的。明顯的特點(diǎn)是在源文件里有一個(gè)繼承CWinApp的類。其又可細(xì)分成靜態(tài)連接到MFC和動(dòng)態(tài)連接到MFC上的。

靜態(tài)連接到MFC的動(dòng)態(tài)連接庫(kù)只被VC的專業(yè)般和企業(yè)版所支持。該類DLL應(yīng)用程序里頭的輸出函數(shù)可以被任意Win32程序使用,包括使用MFC的應(yīng)用程序。輸入函數(shù)有如下形式:
extern "C" EXPORT YourExportedFunction( );
如果沒(méi)有extern “C”修飾,輸出函數(shù)僅僅能從C++代碼中調(diào)用。
DLL應(yīng)用程序從CWinApp派生,但沒(méi)有消息循環(huán)。

動(dòng)態(tài)鏈接到MFC的規(guī)則DLL應(yīng)用程序里頭的輸出函數(shù)可以被任意Win32程序使用,包括使用MFC的應(yīng)用程序。但是,所有從DLL輸出的函數(shù)應(yīng)該以如下語(yǔ)句開始:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
此語(yǔ)句用來(lái)正確地切換MFC模塊狀態(tài)。

Regular DLL能夠被所有支持DLL技術(shù)的語(yǔ)言所編寫的應(yīng)用程序所調(diào)用。在這種動(dòng)態(tài)連接庫(kù)中,它必須有一個(gè)從CWinApp繼承下來(lái)的類,DllMain函數(shù)被MFC所提供,不用自己顯式的寫出來(lái)。

c、Extension DLL:用來(lái)實(shí)現(xiàn)從MFC所繼承下來(lái)的類的重新利用,也就是說(shuō),用這種類型的動(dòng)態(tài)連接庫(kù),可以用來(lái)輸出一個(gè)從MFC所繼承下來(lái)的類。它輸出的函數(shù)僅可以被使用MFC且動(dòng)態(tài)鏈接到MFC的應(yīng)用程序使用??梢詮腗FC繼承你所想要的、更適于你自己用的類,并把它提供給你的應(yīng)用程序。你也可隨意的給你的應(yīng)用程序提供MFC或MFC繼承類的對(duì)象指針。Extension DLL使用MFC的動(dòng)態(tài)連接版本所創(chuàng)建的,并且它只被用MFC類庫(kù)所編寫的應(yīng)用程序所調(diào)用。Extension DLLs 和Regular DLLs不一樣,它沒(méi)有一個(gè)從CWinApp繼承而來(lái)的類的對(duì)象,所以,你必須為自己DllMain函數(shù)添加初始化代碼和結(jié)束代碼。

和規(guī)則DLL相比,有以下不同:

1、它沒(méi)有一個(gè)從CWinApp派生的對(duì)象;
2、它必須有一個(gè)DllMain函數(shù);
3、DllMain調(diào)用AfxInitExtensionModule函數(shù),必須檢查該函數(shù)的返回值,如果返回0,DllMmain也返回0;
4、如果它希望輸出CRuntimeClass類型的對(duì)象或者資源(Resources),則需要提供一個(gè)初始化函數(shù)來(lái)創(chuàng)建一個(gè)CDynLinkLibrary對(duì)象。并且,有必要把初始化函數(shù)輸出;
5、使用擴(kuò)展DLL的MFC應(yīng)用程序必須有一個(gè)從CWinApp派生的類,而且,一般在InitInstance里調(diào)用擴(kuò)展DLL的初始化函數(shù)。

三、dll入口函數(shù):

1、每一個(gè)DLL必須有一個(gè)入口點(diǎn),DllMain是一個(gè)缺省的入口函數(shù)。DllMain負(fù)責(zé)初始化(Initialization)和結(jié)束(Termination)工作,每當(dāng)一個(gè)新的進(jìn)程或者該進(jìn)程的新的線程訪問(wèn)DLL時(shí),或者訪問(wèn)DLL的每一個(gè)進(jìn)程或者線程不再使用DLL或者結(jié)束時(shí),都會(huì)調(diào)用DllMain。但是,使用TerminateProcess或TerminateThread結(jié)束進(jìn)程或者線程,不會(huì)調(diào)用DllMain。

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:是動(dòng)態(tài)庫(kù)被調(diào)用時(shí)所傳遞來(lái)的一個(gè)指向自己的句柄(實(shí)際上,它是指向_DGROUP段的一個(gè)選擇符);
ul_reason_for_call:是一個(gè)說(shuō)明動(dòng)態(tài)庫(kù)被調(diào)原因的標(biāo)志。當(dāng)進(jìn)程或線程裝入或卸載動(dòng)態(tài)連接庫(kù)的時(shí)候,操作系統(tǒng)調(diào)用入口函數(shù),并說(shuō)明動(dòng)態(tài)連接庫(kù)被調(diào)用的原因。它所有的可能值為:
DLL_PROCESS_ATTACH: 進(jìn)程被調(diào)用;
DLL_THREAD_ATTACH: 線程被調(diào)用;
DLL_PROCESS_DETACH: 進(jìn)程被停止;
DLL_THREAD_DETACH: 線程被停止;
lpReserved:是一個(gè)被系統(tǒng)所保留的參數(shù)。

2、_DllMainCRTStartup

?為了使用“C”運(yùn)行庫(kù)(CRT,C Run time Library)的DLL版本(多線程),一個(gè)DLL應(yīng)用程序必須指定_DllMainCRTStartup為入口函數(shù),DLL的初始化函數(shù)必須是DllMain。

?_DllMainCRTStartup完成以下任務(wù):當(dāng)進(jìn)程或線程捆綁(Attach)到DLL時(shí)為“C”運(yùn)行時(shí)的數(shù)據(jù)(C Runtime Data)分配空間和初始化并且構(gòu)造全局“C++”對(duì)象,當(dāng)進(jìn)程或者線程終止使用DLL(Detach)時(shí),清理C Runtime Data并且銷毀全局“C++”對(duì)象。它還調(diào)用DllMain和RawDllMain函數(shù)。

?RawDllMain在DLL應(yīng)用程序動(dòng)態(tài)鏈接到MFC DLL時(shí)被需要,但它是靜態(tài)的鏈接到DLL應(yīng)用程序的。在講述狀態(tài)管理時(shí)解釋其原因。

四、關(guān)于約定:

動(dòng)態(tài)庫(kù)輸出函數(shù)的約定有兩種:調(diào)用約定和名字修飾約定。

1)調(diào)用約定(Calling convention):決定函數(shù)參數(shù)傳送時(shí)入棧和出棧的順序,由調(diào)用者還是被調(diào)用者把參數(shù)彈出棧,以及編譯器用來(lái)識(shí)別函數(shù)名字的修飾約定。

函數(shù)調(diào)用約定有多種,這里簡(jiǎn)單說(shuō)一下:

?? 1、__stdcall調(diào)用約定相當(dāng)于16位動(dòng)態(tài)庫(kù)中經(jīng)常使用的PASCAL調(diào)用約定。在32位的VC++5.0中PASCAL調(diào)用約定不再被支持(實(shí)際上它已被定義為__stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall調(diào)用約定。兩者實(shí)質(zhì)上是一致的,即函數(shù)的參數(shù)自右向左通過(guò)棧傳遞,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧,但不同的是函數(shù)名的修飾部分(關(guān)于函數(shù)名的修飾部分在后面將詳細(xì)說(shuō)明)。

??? _stdcall是Pascal程序的缺省調(diào)用方式,通常用于Win32 Api中,函數(shù)采用從右到左的壓棧方式,自己在退出時(shí)清空堆棧。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。

??? 2、C調(diào)用約定(即用__cdecl關(guān)鍵字說(shuō)明)按從右至左的順序壓參數(shù)入棧,由調(diào)用者把參數(shù)彈出棧。對(duì)于傳送參數(shù)的內(nèi)存棧是由調(diào)用者來(lái)維護(hù)的(正因?yàn)槿绱?,?shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定)。另外,在函數(shù)名修飾約定方面也有所不同。

??? _cdecl是C和C++程序的缺省調(diào)用方式。每一個(gè)調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴。是MFC缺省調(diào)用約定。

??? 3、__fastcall調(diào)用約定是“人”如其名,它的主要特點(diǎn)就是快,因?yàn)樗峭ㄟ^(guò)寄存器來(lái)傳送參數(shù)的(實(shí)際上,它用ECX和EDX傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧),在函數(shù)名修飾約定方面,它和前兩者均不同。

??? _fastcall方式的函數(shù)采用寄存器傳遞參數(shù),VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。???

??? 4、thiscall僅僅應(yīng)用于“C++”成員函數(shù)。this指針存放于CX寄存器,參數(shù)從右到左壓。thiscall不是關(guān)鍵詞,因此不能被程序員指定。

??? 5、naked call采用1-4的調(diào)用約定時(shí),如果必要的話,進(jìn)入函數(shù)時(shí)編譯器會(huì)產(chǎn)生代碼來(lái)保存ESI,EDI,EBX,EBP寄存器,退出函數(shù)時(shí)則產(chǎn)生代碼恢復(fù)這些寄存器的內(nèi)容。naked call不產(chǎn)生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。

??? 關(guān)鍵字 __stdcall、__cdecl和__fastcall可以直接加在要輸出的函數(shù)前,也可以在編譯環(huán)境的Setting...\C/C++ \Code Generation項(xiàng)選擇。當(dāng)加在輸出函數(shù)前的關(guān)鍵字與編譯環(huán)境中的選擇不同時(shí),直接加在輸出函數(shù)前的關(guān)鍵字有效。它們對(duì)應(yīng)的命令行參數(shù)分別為/Gz、/Gd和/Gr。缺省狀態(tài)為/Gd,即__cdecl。

??? 要完全模仿PASCAL調(diào)用約定首先必須使用__stdcall調(diào)用約定,至于函數(shù)名修飾約定,可以通過(guò)其它方法模仿。還有一個(gè)值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數(shù)翻譯成適當(dāng)?shù)恼{(diào)用約定,在WIN32中,它被定義為__stdcall。使用WINAPI宏可以創(chuàng)建自己的APIs。

2)名字修飾約定

1、修飾名(Decoration name)

“C”或者“C++”函數(shù)在內(nèi)部(編譯和鏈接)通過(guò)修飾名識(shí)別。修飾名是編譯器在編譯函數(shù)定義或者原型時(shí)生成的字符串。有些情況下使用函數(shù)的修飾名是必要的,如在模塊定義文件里頭指定輸出“C++”重載函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù),又如在匯編代碼里調(diào)用“C””或“C++”函數(shù)等。

修飾名由函數(shù)名、類名、調(diào)用約定、返回類型、參數(shù)等共同決定。

2、名字修飾約定隨調(diào)用約定和編譯種類(C或C++)的不同而變化。函數(shù)名修飾約定隨編譯種類和調(diào)用約定的不同而不同,下面分別說(shuō)明。

??? a、C編譯時(shí)函數(shù)名修飾約定規(guī)則:

?__stdcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)下劃線前綴,后面加上一個(gè)“@”符號(hào)和其參數(shù)的字節(jié)數(shù),格式為_functionname@number。

?__cdecl調(diào)用約定僅在輸出函數(shù)名前加上一個(gè)下劃線前綴,格式為_functionname。
??
?__fastcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)“@”符號(hào),后面也是一個(gè)“@”符號(hào)和其參數(shù)的字節(jié)數(shù),格式為@functionname@number。

??? 它們均不改變輸出函數(shù)名中的字符大小寫,這和PASCAL調(diào)用約定不同,PASCAL約定輸出的函數(shù)名無(wú)任何修飾且全部大寫。

??? b、C++編譯時(shí)函數(shù)名修飾約定規(guī)則:

__stdcall調(diào)用約定:
????????? 1、以“?”標(biāo)識(shí)函數(shù)名的開始,后跟函數(shù)名;
????????? 2、函數(shù)名后面以“@@YG”標(biāo)識(shí)參數(shù)表的開始,后跟參數(shù)表;
????????? 3、參數(shù)表以代號(hào)表示:
???????????? X--void ,
???????????? D--char,
???????????? E--unsigned char,
???????????? F--short,
???????????? H--int,
???????????? I--unsigned int,
???????????? J--long,
???????????? K--unsigned long,
???????????? M--float,
???????????? N--double,
???????????? _N--bool,
???????????? ....
???????????? PA--表示指針,后面的代號(hào)表明指針類型,如果相同類型的指針連續(xù)出現(xiàn),以“0”代替,一個(gè)“0”代表一次重復(fù);
????????? 4、參數(shù)表的第一項(xiàng)為該函數(shù)的返回值類型,其后依次為參數(shù)的數(shù)據(jù)類型,指針標(biāo)識(shí)在其所指數(shù)據(jù)類型前;
????????? 5、參數(shù)表后以“@Z”標(biāo)識(shí)整個(gè)名字的結(jié)束,如果該函數(shù)無(wú)參數(shù),則以“Z”標(biāo)識(shí)結(jié)束。

??? 其格式為“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如
????????? int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z
????????? void Test2()?????????????????????? -----“?Test2@@YGXXZ

__cdecl調(diào)用約定:
?規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開始標(biāo)識(shí)由上面的“@@YG”變?yōu)?a href="mailto:“@@YA">“@@YA”。

__fastcall調(diào)用約定:
?規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開始標(biāo)識(shí)由上面的“@@YG”變?yōu)?a href="mailto:“@@YI">“@@YI”。

??? VC++對(duì)函數(shù)的省缺聲明是"__cedcl",將只能被C/C++調(diào)用.
???
五、關(guān)于DLL的函數(shù):

??? 動(dòng)態(tài)鏈接庫(kù)中定義有兩種函數(shù):導(dǎo)出函數(shù)(export function)和內(nèi)部函數(shù)(internal function)。導(dǎo)出函數(shù)可以被其它模塊調(diào)用,內(nèi)部函數(shù)在定義它們的DLL程序內(nèi)部使用。

輸出函數(shù)的方法有以下幾種:

1、傳統(tǒng)的方法

?在模塊定義文件的EXPORT部分指定要輸入的函數(shù)或者變量。語(yǔ)法格式如下:
entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]

其中:

entryname是輸出的函數(shù)或者數(shù)據(jù)被引用的名稱;

internalname同entryname;

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

NONAME僅僅在按順序號(hào)輸出時(shí)被使用(不使用entryname);

DATA表示輸出的是數(shù)據(jù)項(xiàng),使用DLL輸出數(shù)據(jù)的程序必須聲明該數(shù)據(jù)項(xiàng)為_declspec(dllimport)。

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

?對(duì)于“C”函數(shù)來(lái)說(shuō),entryname可以等同于函數(shù)名;但是對(duì)“C++”函數(shù)(成員函數(shù)、非成員函數(shù))來(lái)說(shuō),entryname是修飾名??梢詮?map映像文件中得到要輸出函數(shù)的修飾名,或者使用DUMPBIN /SYMBOLS得到,然后把它們寫在.def文件的輸出模塊。DUMPBIN是VC提供的一個(gè)工具。

如果要輸出一個(gè)“C++”類,則把要輸出的數(shù)據(jù)和成員的修飾名都寫入.def模塊定義文件。

2、在命令行輸出

?對(duì)鏈接程序LINK指定/EXPORT命令行參數(shù),輸出有關(guān)函數(shù)。

3、使用MFC提供的修飾符號(hào)_declspec(dllexport)

?在要輸出的函數(shù)、類、數(shù)據(jù)的聲明前加上_declspec(dllexport)的修飾符,表示輸出。__declspec(dllexport)在C調(diào)用約定、C編譯情況下可以去掉輸出函數(shù)名的下劃線前綴。extern "C"使得在C++中使用C編譯方式成為可能。在“C++”下定義“C”函數(shù),需要加extern “C”關(guān)鍵詞。用extern "C"來(lái)指明該函數(shù)使用C編譯方式。輸出的“C”函數(shù)可以從“C”代碼里調(diào)用。
???
??? 例如,在一個(gè)C++文件中,有如下函數(shù):
??? extern "C" {void? __declspec(dllexport) __cdecl Test(int var);}
其輸出函數(shù)名為: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

?像AFX_EXT_CLASS這樣的宏,如果用于DLL應(yīng)用程序的實(shí)現(xiàn)中,則表示輸出(因?yàn)開AFX_EXT被定義,通常是在編譯器的標(biāo)識(shí)參數(shù)中指定該選項(xiàng)/D_AFX_EXT);如果用于使用DLL的應(yīng)用程序中,則表示輸入(_AFX_EXT沒(méi)有定義)。

?要輸出整個(gè)的類,對(duì)類使用_declspec(_dllexpot);要輸出類的成員函數(shù),則對(duì)該函數(shù)使用_declspec(_dllexport)。如:

class AFX_EXT_CLASS CTextDoc : public CDocument
{
?…
}

extern "C" AFX_EXT_API void WINAPI InitMYDLL();

?這幾種方法中,最好采用第三種,方便好用;其次是第一種,如果按順序號(hào)輸出,調(diào)用效率會(huì)高些;最次是第二種。?

六、模塊定義文件(.DEF)

?模塊定義文件(.DEF)是一個(gè)或多個(gè)用于描述DLL屬性的模塊語(yǔ)句組成的文本文件,每個(gè)DEF文件至少必須包含以下模塊定義語(yǔ)句:

* 第一個(gè)語(yǔ)句必須是LIBRARY語(yǔ)句,指出DLL的名字;
* EXPORTS語(yǔ)句列出被導(dǎo)出函數(shù)的名字;將要輸出的函數(shù)修飾名羅列在EXPORTS之下,這個(gè)名字必須與定義函數(shù)的名字完全一致,如此就得到一個(gè)沒(méi)有任何修飾的函數(shù)名了。
* 可以使用DESCRIPTION語(yǔ)句描述DLL的用途(此句可選);
* ";"對(duì)一行進(jìn)行注釋(可選)。

七、DLL程序和調(diào)用其輸出函數(shù)的程序的關(guān)系

1、dll與進(jìn)程、線程之間的關(guān)系

DLL模塊被映射到調(diào)用它的進(jìn)程的虛擬地址空間。
DLL使用的內(nèi)存從調(diào)用進(jìn)程的虛擬地址空間分配,只能被該進(jìn)程的線程所訪問(wèn)。
DLL的句柄可以被調(diào)用進(jìn)程使用;調(diào)用進(jìn)程的句柄可以被DLL使用。
DLL使用調(diào)用進(jìn)程的棧。

2、關(guān)于共享數(shù)據(jù)段

?DLL定義的全局變量可以被調(diào)用進(jìn)程訪問(wèn);DLL可以訪問(wèn)調(diào)用進(jìn)程的全局?jǐn)?shù)據(jù)。使用同一DLL的每一個(gè)進(jìn)程都有自己的DLL全局變量實(shí)例。如果多個(gè)線程并發(fā)訪問(wèn)同一變量,則需要使用同步機(jī)制;對(duì)一個(gè)DLL的變量,如果希望每個(gè)使用DLL的線程都有自己的值,則應(yīng)該使用線程局部存儲(chǔ)(TLS,Thread Local Strorage)。

??? 在程序里加入預(yù)編譯指令,或在開發(fā)環(huán)境的項(xiàng)目設(shè)置里也可以達(dá)到設(shè)置數(shù)據(jù)段屬性的目的.必須給這些變量賦初值,否則編譯器會(huì)把沒(méi)有賦初始值的變量放在一個(gè)叫未被初始化的數(shù)據(jù)段中。

posted on 2006-12-04 11:00 @王一偉 閱讀(442) 評(píng)論(0)  編輯 收藏 引用

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品视频在线观看| 性色av一区二区三区红粉影视| 麻豆精品一区二区av白丝在线| 欧美成人精品一区| 亚洲韩国青草视频| 欧美日韩精品在线观看| 亚洲一区二区欧美日韩| 欧美亚洲日本国产| 禁断一区二区三区在线| 欧美—级在线免费片| 一区二区三区高清不卡| 久久久久久成人| 91久久精品视频| 欧美日韩福利视频| 午夜精彩视频在线观看不卡| 欧美1区2区| 亚洲视屏一区| 韩国av一区二区三区| 欧美成人三级在线| 亚洲午夜在线| 欧美成人免费在线| 亚洲欧美精品中文字幕在线| 国产综合欧美| 欧美欧美全黄| 久久福利电影| 亚洲精品日韩在线观看| 久久久久久久久久久久久9999| 最新国产の精品合集bt伙计| 国产精品永久| 嫩草影视亚洲| 午夜在线电影亚洲一区| 亚洲日韩欧美视频一区| 午夜精品免费| 日韩一级黄色大片| 国产综合色一区二区三区| 欧美国产日韩亚洲一区| 欧美在线国产精品| 99国产精品99久久久久久| 蜜桃av久久久亚洲精品| 欧美一区二区国产| 夜夜嗨av一区二区三区网页| 尤物yw午夜国产精品视频| 国产精品视频yy9099| 欧美精品久久久久a| 久久久国产精品一区二区三区| 在线亚洲美日韩| 亚洲成人在线视频播放 | 亚洲小视频在线观看| 女仆av观看一区| 欧美在线精品免播放器视频| 日韩亚洲一区在线播放| 亚洲大黄网站| 激情综合电影网| 国产欧美精品一区二区三区介绍| 欧美精品在线一区| 免费欧美日韩国产三级电影| 欧美一级理论片| 亚洲欧美日韩国产中文在线| 日韩视频免费在线| 91久久国产综合久久蜜月精品| 久久综合一区二区三区| 久久国产精品99精品国产| 亚洲一级特黄| 一区二区欧美国产| 日韩午夜激情| 亚洲精品字幕| 亚洲国产精品999| 娇妻被交换粗又大又硬视频欧美| 国产精品自在在线| 国产精品欧美日韩久久| 国产精品久久久久久久久久久久久| 欧美精品色综合| 欧美精品一区二区精品网| 你懂的网址国产 欧美| 鲁大师影院一区二区三区| 久久综合999| 美女91精品| 欧美大片第1页| 欧美国产在线观看| 欧美日韩理论| 国产精品a久久久久| 国产精品高清一区二区三区| 国产精品美女诱惑| 国产女主播在线一区二区| 国内精品久久久久久影视8| 国内精品久久久久久久影视麻豆 | 亚洲黄色在线看| 亚洲美女诱惑| 亚洲天堂av电影| 亚洲你懂的在线视频| 欧美在现视频| 另类欧美日韩国产在线| 欧美大尺度在线| 亚洲伦理网站| 亚洲影院高清在线| 久久狠狠久久综合桃花| 麻豆国产va免费精品高清在线| 欧美激情欧美狂野欧美精品 | 午夜精品久久久久影视| 久久精品国产清高在天天线| 麻豆国产精品va在线观看不卡| 欧美xx视频| 日韩一二三区视频| 性欧美精品高清| 免费av成人在线| 欧美日韩综合不卡| 国产一区二区主播在线| 亚洲欧洲精品成人久久奇米网 | 亚洲自拍三区| 久久国产精品黑丝| 韩曰欧美视频免费观看| 亚洲精品极品| 欧美一区日韩一区| 欧美激情一区二区三区在线| 一本色道婷婷久久欧美| 久久久久99| 欧美日韩在线视频一区| 红桃视频国产精品| 国产精品99久久久久久久久久久久| 久久aⅴ国产欧美74aaa| 亚洲国产91| 性欧美videos另类喷潮| 欧美另类一区二区三区| 国产日韩欧美一区| 一本久久青青| 老司机精品视频网站| 这里是久久伊人| 欧美成人免费va影院高清| 国产欧美日韩视频一区二区三区| 最新成人在线| 久久人人精品| 亚洲一区二三| 欧美日韩精品伦理作品在线免费观看| 狠狠色狠狠色综合人人| 亚洲欧美日韩第一区| 亚洲国产女人aaa毛片在线| 性久久久久久久| 欧美视频一区二区三区在线观看 | 国产视频观看一区| 宅男噜噜噜66国产日韩在线观看| 久久影院午夜片一区| 亚洲综合久久久久| 欧美日韩国产精品专区| 亚洲国产日日夜夜| 久久综合影视| 新狼窝色av性久久久久久| 欧美午夜宅男影院在线观看| 99re8这里有精品热视频免费 | 亚洲三级视频在线观看| 美女露胸一区二区三区| 久久不见久久见免费视频1| 国产精品久久久久久久久婷婷 | 亚洲欧美日韩一区二区在线 | 亚洲香蕉视频| 亚洲激情小视频| 欧美1区2区视频| 亚洲福利久久| 欧美国产日本韩| 麻豆精品网站| 亚洲人成绝费网站色www| 欧美成人性生活| 久久精品国产v日韩v亚洲 | 国产乱人伦精品一区二区| 亚洲综合二区| 一区二区三区日韩| 国产精品久久久久久久久搜平片 | 国产农村妇女毛片精品久久莱园子| 亚洲视频导航| 亚洲性夜色噜噜噜7777| 国产伦一区二区三区色一情| 欧美一区二区视频在线观看2020 | 久久亚洲精品一区| 亚洲国产成人精品久久| 欧美激情精品久久久六区热门 | 亚洲欧洲日产国产网站| 欧美激情免费在线| 欧美日韩国产在线| 亚洲一区二区三区国产| 午夜激情综合网| 一区二区亚洲精品国产| 欧美激情视频给我| 欧美日本中文字幕| 性亚洲最疯狂xxxx高清| 欧美一区二区三区视频在线观看| 国产在线视频欧美一区二区三区| 免费成人av在线| 欧美理论电影在线观看| 亚洲欧美www| 久久精品成人| 99国产精品99久久久久久粉嫩| 一区二区三区黄色| 国产综合18久久久久久| 亚洲国产欧美在线人成| 欧美性天天影院| 久久久99国产精品免费| 免费观看成人鲁鲁鲁鲁鲁视频| 一区二区激情小说| 亚洲欧美视频一区二区三区| 欲色影视综合吧| 亚洲免费久久|