dll和lib的區(qū)別(轉(zhuǎn))
dll和lib的區(qū)別 lib文件是在link的時候用 .dll文件是在Run的時候用 lib 是靜態(tài)鏈接庫 dll 是動態(tài)鏈接庫dll需要和程序一起發(fā)布才行 lib編譯后就不需要了 lib將在連接時把一些代碼拷貝到你的程序代碼里,所以叫做靜態(tài)連接dll是程序運行時把dll里的代碼和資源加再到進程地址空間去,所以叫動態(tài)連接 動態(tài)鏈接與靜態(tài)鏈接的不同之處在于:動態(tài)鏈接允許可執(zhí)行模塊(.dll文件或 .exe 文件)僅包含在運行時定位 DLL函數(shù)的可執(zhí)行代碼所需的信息。在靜態(tài)鏈接中,鏈接器從靜態(tài)鏈接庫獲取所有被引用的函數(shù),并將庫同代碼一起放到可執(zhí)行文件中。lib與dll文件最大區(qū)別在調(diào)用方面 dll可以靜態(tài)陷入 .LIB 靜態(tài)連接庫(生成可執(zhí)行文件)。 .DLL動態(tài)連接庫(運行時加載)。 .lib.dll都是編譯了的可執(zhí)行代碼 所不同的是,.lib中的執(zhí)行代碼的內(nèi)容在你自己寫的程序的編譯過程中被拷貝了一份,而dll只是標(biāo)記了一個對這個dll文件的某一段代碼(函數(shù))的引用,你的程序運行時必須有 這一個.dll文件 調(diào)用方法存在不同使用LIB,你在工程內(nèi)部不用調(diào)用LoadLibrary及GetProcAddress. 一、關(guān)于調(diào)用方式:1、靜態(tài)調(diào)用方式:由編譯系統(tǒng)完成對DLL的加載和應(yīng)用程序結(jié)束時DLL卸載的編碼(如還有其它程序使用該DLL,則Windows對DLL的應(yīng)用記錄減1,直到所有相關(guān)程序都結(jié)束對該DLL的使用時才釋放它),簡單實用,但不夠靈活,只能滿足一般要求。隱式的調(diào)用:需要把產(chǎn)生動態(tài)連接庫時產(chǎn)生的.LIB文件加入到應(yīng)用程序的工程中,想使用DLL中的函數(shù)時,只須說明一下。隱式調(diào)用不需要調(diào)用LoadLibrary()和FreeLibrary()。程序員在建立一個DLL文件時,鏈接程序會自動生成一個與之對應(yīng)的LIB導(dǎo)入文件。該文件包含了每一個DLL導(dǎo)出函數(shù)的符號名和可選的標(biāo)識號,但是并不含有實際的代碼。LIB文件作為DLL的替代文件被編譯到應(yīng)用程序項目中。當(dāng)程序員通過靜態(tài)鏈接方式編譯生成應(yīng)用程序時,應(yīng)用程序中的調(diào)用函數(shù)與LIB文件中導(dǎo)出符號相匹配,這些符號或標(biāo)識號進入到生成的EXE文件中。LIB文件中也包含了對應(yīng)的DLL文件名(但不是完全的路徑名),鏈接程序?qū)⑵浯鎯υ贓XE文件內(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)存中。可執(zhí)行程序鏈接到一個包含DLL輸出函數(shù)信息的輸入庫文件(.LIB文件)。操作系統(tǒng)在加載使用可執(zhí)行程序時加載DLL。可執(zhí)行程序直接通過函數(shù)名調(diào)用DLL的輸出函數(shù),調(diào)用方法和程序內(nèi)部其他的函數(shù)是一樣的。2、動態(tài)調(diào)用方式:是由編程者用API函數(shù)加載和卸載DLL來達(dá)到調(diào)用DLL的目的,使用上較復(fù)雜,但能更加有效地使用內(nèi)存,是編制大型應(yīng)用程序時的重要方式。顯式的調(diào)用:是指在應(yīng)用程序中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動態(tài)連接庫調(diào)進來,動態(tài)連接庫的文件名即是上面兩個函數(shù)的參數(shù),再用GetProcAddress()獲取想要引入的函數(shù)。自此,你就可以象使用如同本應(yīng)用程序自定義的函數(shù)一樣來調(diào)用此引入函數(shù)了。在應(yīng)用程序退出之前,應(yīng)該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動態(tài)連接庫。直接調(diào)用Win32的LoadLibary函數(shù),并指定DLL的路徑作為參數(shù)。LoadLibary返回HINSTANCE參數(shù),應(yīng)用程序在調(diào)用GetProcAddress函數(shù)時使用這一參數(shù)。GetProcAddress函數(shù)將符號名或標(biāo)識號轉(zhuǎn)換為DLL內(nèi)部的地址。程序員可以決定DLL文件何時加載或不加載,顯式鏈接在運行時決定加載哪個DLL文件。使用DLL的程序在使用之前必須加載(LoadLibrary)加載DLL從而得到一個DLL模塊的句柄,然后調(diào)用GetProcAddress函數(shù)得到輸出函數(shù)的指針,在退出之前必須卸載DLL(FreeLibrary)。Windows將遵循下面的搜索順序來定位DLL: 1.包含EXE文件的目錄, 2.進程的當(dāng)前工作目錄, 3.Windows系統(tǒng)目錄,4.Windows目錄, 5.列在Path環(huán)境變量中的一系列目錄。 五、關(guān)于DLL的函數(shù): 動態(tài)鏈接庫中定義有兩種函數(shù):導(dǎo)出函數(shù)(exportfunction)和內(nèi)部函數(shù)(internal function)。導(dǎo)出函數(shù)可以被其它模塊調(diào)用,內(nèi)部函數(shù)在定義它們的DLL程序內(nèi)部使用。輸出函數(shù)的方法有以下幾種: 1、傳統(tǒng)的方法 在模塊定義文件的EXPORT部分指定要輸入的函數(shù)或者變量。語法格式如下:entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE] 其中:entryname是輸出的函數(shù)或者數(shù)據(jù)被引用的名稱; internalname同entryname;@ordinal表示在輸出表中的順序號(index); NONAME僅僅在按順序號輸出時被使用(不使用entryname);DATA表示輸出的是數(shù)據(jù)項,使用DLL輸出數(shù)據(jù)的程序必須聲明該數(shù)據(jù)項為_declspec(dllimport)。上述各項中,只有entryname項是必須的,其他可以省略。對于“C”函數(shù)來說,entryname可以等同于函數(shù)名;但是對“C++”函數(shù)(成員函數(shù)、非成員函數(shù))來說,entryname是修飾名。可以從.map映像文件中得到要輸出函數(shù)的修飾名,或者使用DUMPBIN/SYMBOLS得到,然后把它們寫在.def文件的輸出模塊。DUMPBIN是VC提供的一個工具。如果要輸出一個“C++”類,則把要輸出的數(shù)據(jù)和成員的修飾名都寫入.def模塊定義文件。 2、在命令行輸出對鏈接程序LINK指定/EXPORT命令行參數(shù),輸出有關(guān)函數(shù)。 3、使用MFC提供的修飾符號_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"來指明該函數(shù)使用C編譯方式。輸出的“C”函數(shù)可以從“C”代碼里調(diào)用。 例如,在一個C++文件中,有如下函數(shù): extern "C"{void __declspec(dllexport) __cdecl Test(int var);} 其輸出函數(shù)名為:TestMFC提供了一些宏,就有這樣的作用。 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 _AFXEXTAFX_CLASS_EXPORT #else AFX_CLASS_IMPORT AFX_EXT_API:#ifdef _AFXEXTAFX_API_EXPORT #else AFX_API_IMPORT AFX_EXT_DATA:#ifdef _AFXEXTAFX_DATA_EXPORT #else AFX_DATA_IMPORT像AFX_EXT_CLASS這樣的宏,如果用于DLL應(yīng)用程序的實現(xiàn)中,則表示輸出(因為_AFX_EXT被定義,通常是在編譯器的標(biāo)識參數(shù)中指定該選項/D_AFX_EXT);如果用于使用DLL的應(yīng)用程序中,則表示輸入(_AFX_EXT沒有定義)。要輸出整個的類,對類使用_declspec(_dllexpot);要輸出類的成員函數(shù),則對該函數(shù)使用_declspec(_dllexport)。如: class AFX_EXT_CLASS CTextDoc : public CDocument { … } extern "C"AFX_EXT_API void WINAPI InitMYDLL();這幾種方法中,最好采用第三種,方便好用;其次是第一種,如果按順序號輸出,調(diào)用效率會高些;最次是第二種。編譯生成dll文件后,我們同時得到lib文件。這個lib和靜態(tài)鏈接庫的lib文件有何區(qū)別?謝謝!怎么可能一樣呢,和DLL一起生成.lib內(nèi)只有函數(shù)名等信息,而不包括實現(xiàn)信息。不一樣. 1 靜態(tài)lib中,有實現(xiàn)的代碼 2而dll輸出的lib,只有連接信息.(即export項中的函數(shù)入口地址) 這樣,調(diào)用模塊可以模擬這個lib去修改相應(yīng)的import項對,不一樣。 靜態(tài)lib鏈接后就不要lib的支持了,lib中的代碼會合并到exe文件中。dll的lib鏈接后還要dll的支持。 1 靜態(tài)lib中,包含實現(xiàn)的二進制碼,連接時直接連入Exe文件的地址空間。 2dll輸出的lib,僅含導(dǎo)出函數(shù)的地址和一些位址信息,可以幫助Link程序完成連接(在此時安排調(diào)用入口地址及函數(shù)回調(diào)信息)。這樣,在運行時才將DLL中真正的代碼調(diào)入執(zhí)行,實現(xiàn)動態(tài)連接。那我想知道靜態(tài)的Lib怎么作?怎么將DLL作為靜態(tài)編譯。 VC里有l(wèi)ib和implib,都可以從.dll產(chǎn)生對應(yīng)的.lib 如:lib /DEF:SCSIIO.DLL 如何從dll文件導(dǎo)出對應(yīng)的lib文件? Visual C++開發(fā)工具提供了兩個命令行工具,一個是dumpbin.exe,另一個是lib.exe。利用這兩個工具即可從dll導(dǎo)出其對應(yīng)的lib。1、在命令行執(zhí)行: dumpbin /exports yourdll.dll > yourdll.def 2、編輯 yourdll.def文件,使之格式與.def文件格式一致。比如: EXPORTS; fn1; fn2; 3、在命令行執(zhí)行: lib/def:yourdll.def /machine:i386 /out:yourdll.lib