【目錄】
首先介紹一下靜態(tài)庫(靜態(tài)鏈接庫)、動(dòng)態(tài)庫(動(dòng)態(tài)鏈接庫)的概念,首先兩者都是代碼共享的方式。
靜態(tài)庫:在鏈接步驟中,連接器將從庫文件取得所需的代碼,復(fù)制到生成的可執(zhí)行文件中,這種庫稱為靜態(tài)庫,其特點(diǎn)是可執(zhí)行文件中包含了庫代碼的一份完整拷貝;缺點(diǎn)就是被多次使用就會(huì)有多份冗余拷貝。即靜態(tài)庫中的指令都全部被直接包含在最終生成的 EXE 文件中了。在vs中新建生成靜態(tài)庫的工程,編譯生成成功后,只產(chǎn)生一個(gè).lib文件
動(dòng)態(tài)庫:動(dòng)態(tài)鏈接庫是一個(gè)包含可由多個(gè)程序同時(shí)使用的代碼和數(shù)據(jù)的庫,DLL不是可執(zhí)行文件。動(dòng)態(tài)鏈接提供了一種方法,使進(jìn)程可以調(diào)用不屬于其可執(zhí)行代碼的函數(shù)。函數(shù)的可執(zhí)行代碼位于一個(gè) DLL 中,該 DLL 包含一個(gè)或多個(gè)已被編譯、鏈接并與使用它們的進(jìn)程分開存儲(chǔ)的函數(shù)。在vs中新建生成動(dòng)態(tài)庫的工程,編譯成功后,產(chǎn)生一個(gè).lib文件和一個(gè).dll文件
那么上述靜態(tài)庫和動(dòng)態(tài)庫中的lib有什么區(qū)別呢?
靜態(tài)庫中的lib:該LIB包含函數(shù)代碼本身(即包括函數(shù)的索引,也包括實(shí)現(xiàn)),在編譯時(shí)直接將代碼加入程序當(dāng)中
動(dòng)態(tài)庫中的lib:該LIB包含了函數(shù)所在的DLL文件和文件中函數(shù)位置的信息(索引),函數(shù)實(shí)現(xiàn)代碼由運(yùn)行時(shí)加載在進(jìn)程空間中的DLL提供
總之,lib是編譯時(shí)用到的,dll是運(yùn)行時(shí)用到的。如果要完成源代碼的編譯,只需要lib;如果要使動(dòng)態(tài)鏈接的程序運(yùn)行起來,只需要dll。
以下例子均在vs2010上測試
生成動(dòng)態(tài)庫
新建項(xiàng)目--win32項(xiàng)目--填寫項(xiàng)目名--確定--下一步--應(yīng)用程序類型:選擇dll--附加選項(xiàng):選擇導(dǎo)出符號(hào)--完成
可以看到生成了一個(gè)dllmain.cpp 文件,這是dll應(yīng)用程序的入口,注意它和普通工程的入口main函數(shù)不同,這個(gè)文件我們不需要修改。
在這個(gè)動(dòng)態(tài)庫中我們舉例導(dǎo)出一個(gè)變量,一個(gè)類,一個(gè)函數(shù),頭文件dll.h如下:
1 //新建生成dll的工程時(shí),vs默認(rèn)定義了宏DLL_EXPORT,因此,DLL_API 是 __declspec(dllexport),用來導(dǎo)出 2 //當(dāng)我們?cè)陟o態(tài)調(diào)用dll時(shí),我們包含該頭文件,由于沒有定義DLL_EXPORT,所以DLL_API是 3 //__declspec(dllimport),用來導(dǎo)入 4 #ifdef DLL_EXPORTS 5 #define DLL_API __declspec(dllexport) 6 #else 7 #define DLL_API __declspec(dllimport) 8 #endif 9 10 // 導(dǎo)出類11 class DLL_API Cdll {12 public:13 Cdll(void);14 // TODO: 在此添加您的方法。15 };16 17 //導(dǎo)出變量,變量在.cpp文件中定義18 extern DLL_API int ndll;19 20 //導(dǎo)出函數(shù),加extern "C",是為了保證編譯時(shí)生成的函數(shù)名不變,這樣動(dòng)態(tài)調(diào)用dll時(shí)才能21 //正確獲取函數(shù)的地址22 extern "C" DLL_API int fndll(void);
dll.cpp 文件如下:
1 #include "dll.h" 2 3 4 // 這是導(dǎo)出變量的一個(gè)示例 5 DLL_API int ndll=6; 6 7 // 這是導(dǎo)出函數(shù)的一個(gè)示例。 8 DLL_API int fndll(void) 9 {10 return 42;11 }12 13 // 這是已導(dǎo)出類的構(gòu)造函數(shù)。14 // 有關(guān)類定義的信息,請(qǐng)參閱 dll.h15 Cdll::Cdll()16 {17 return;18 }
有兩種方法調(diào)用動(dòng)態(tài)庫,一種隱式鏈接,一種顯示鏈接。
調(diào)用動(dòng)態(tài)庫:隱式鏈接
隱式鏈接 需要.h文件,dll文件,lib文件
(1)將dll放到工程的工作目錄
(2)設(shè)置項(xiàng)目屬性--vc++目錄--庫目錄為lib所在的路徑
(3)將lib添加到項(xiàng)目屬性--鏈接器--輸入--附加依賴項(xiàng)(或者直接在源代碼中加入#pragma comment(lib, “**.lib”))
(4)在源文件中添加.h頭文件
然后就像平常一樣調(diào)用普通函數(shù)、類、變量
調(diào)用動(dòng)態(tài)庫:顯示鏈接
顯示鏈接 只需要.dll文件,但是這種調(diào)用方式不能調(diào)用dll中的變量或者類(其實(shí)可以調(diào)用類,但是相當(dāng)麻煩,有興趣者可參考http://blog.csdn.net/jdcb2001/article/details/1394883)
顯示調(diào)用主要使用WIN32 API函數(shù)LoadLibrary、GetProcAddress,舉例如下:
1 typedef int (*dllfun)(void);//定義指向dll中函數(shù)的函數(shù)指針 2 HINSTANCE hlib = LoadLibrary(".\\dll.dll"); 3 if(!hlib) 4 { 5 std::cout<<"load dll error\n"; 6 return -1; 7 } 8 dllfun fun = (dllfun)GetProcAddress(hlib,"fndll"); 9 if(!fun)10 {11 std::cout<<"load fun error\n";12 return -1;13 }14 fun();
生成靜態(tài)庫
新建項(xiàng)目--win32項(xiàng)目--填寫項(xiàng)目名--確定--下一步--應(yīng)用程序類型:選擇靜態(tài)庫
靜態(tài)庫項(xiàng)目沒有main函數(shù),也沒有像dll項(xiàng)目中的dllmain。
創(chuàng)建項(xiàng)目后添加.h文件,添加相應(yīng)的導(dǎo)出函數(shù)、變量或類,如下所示
1 #ifndef _MYLIB_H_ 2 #define _MYLIB_H_ 3 4 void fun(int a); 5 6 extern int k; 7 8 class testclass 9 {10 public:11 testclass();12 void print();13 };14 15 #endif
.cpp文件如下
1 #include "stdafx.h" 2 #include "lib.h" 3 #include <iostream> 4 5 void fun(int a) 6 { 7 std::cout<<a<<"lib gen\n"; 8 } 9 10 int k = 222;11 12 testclass::testclass()13 {14 std::cout<<"123\n";15 }16 17 void testclass::print()18 {19 std::cout<<"this is testcalss\n";20 }
編譯工程后就會(huì)生成一個(gè).lib文件
需要.h文件,lib文件
(1)設(shè)置項(xiàng)目屬性--vc++目錄--庫目錄為lib所在的路徑
(2)將lib添加到項(xiàng)目屬性--鏈接器--輸入--附加依賴項(xiàng)(或者直接在源代碼中加入#pragma comment(lib, “**.lib”))
(3)在源文件中添加.h頭文件
然后就像平常一樣調(diào)用普通函數(shù)、類、變量,舉例如下:
1 #include <iostream> 2 #include "lib.h" 3 4 #pragma comment(lib, "lib.lib") 5 6 int main() 7 { 8 fun(4); 9 std::cout<<k<<std::endl;10 testclass tc; 11 tc.print();12 return 0;13 }
【版權(quán)聲明】轉(zhuǎn)載請(qǐng)注明出處 http://www.cnblogs.com/TenosDoIt/p/3203137.html
轉(zhuǎn)這篇文章是因?yàn)橐郧坝袀€(gè)誤區(qū),以為lib為靜態(tài)庫,dll為動(dòng)態(tài)庫,這理解并不錯(cuò),但不全面。lib分兩種的:
(1) lib包含所有內(nèi)容的靜態(tài)庫,應(yīng)用程序用它即可,這是我理解的一種
(2) lib只包含頭部信息,為了配合dll使用,dll包含函數(shù)內(nèi)容,這先前我不知道,以為dll本身包含了函數(shù)地址及內(nèi)容。此時(shí),可以觀察出lib比dll小很多:
curllib.dll 190KB
curllib.lib 14KB
curllib_static.lib 1857KB
本來是想上圖的,網(wǎng)速不給力。curllib.dll包含了函數(shù)內(nèi)容,190KB,curllib.lib只是些函數(shù)入口,用于編譯,只有14KB,而curllib_static.lib包含了所有,1857KB,比dll還要大。
第二點(diǎn)與linux, unix系統(tǒng)很不同,在linux/unix上,.so已經(jīng)包含了函數(shù)頭部信息及內(nèi)容,不需要一個(gè).a的靜態(tài)庫作為編譯.
聯(lián)系客服