【目錄】
首先介紹一下靜態庫(靜態鏈接庫)、動態庫(動態鏈接庫)的概念,首先兩者都是代碼共享的方式。
靜態庫:在鏈接步驟中,連接器將從庫文件取得所需的代碼,復制到生成的可執行文件中,這種庫稱為靜態庫,其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗余拷貝。即靜態庫中的指令都全部被直接包含在最終生成的 EXE 文件中了。在vs中新建生成靜態庫的工程,編譯生成成功后,只產生一個.lib文件
動態庫:動態鏈接庫是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。在vs中新建生成動態庫的工程,編譯成功后,產生一個.lib文件和一個.dll文件
那么上述靜態庫和動態庫中的lib有什么區別呢?
靜態庫中的lib:該LIB包含函數代碼本身(即包括函數的索引,也包括實現),在編譯時直接將代碼加入程序當中
動態庫中的lib:該LIB包含了函數所在的DLL文件和文件中函數位置的信息(索引),函數實現代碼由運行時加載在進程空間中的DLL提供
總之,lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。
以下例子均在vs2010上測試
生成動態庫
新建項目--win32項目--填寫項目名--確定--下一步--應用程序類型:選擇dll--附加選項:選擇導出符號--完成
可以看到生成了一個dllmain.cpp 文件,這是dll應用程序的入口,注意它和普通工程的入口main函數不同,這個文件我們不需要修改。
在這個動態庫中我們舉例導出一個變量,一個類,一個函數,頭文件dll.h如下:
1 //新建生成dll的工程時,vs默認定義了宏DLL_EXPORT,因此,DLL_API 是 __declspec(dllexport),用來導出 2 //當我們在靜態調用dll時,我們包含該頭文件,由於沒有定義DLL_EXPORT,所以DLL_API是 3 //__declspec(dllimport),用來導入 4 #ifdef DLL_EXPORTS 5 #define DLL_API __declspec(dllexport) 6 #else 7 #define DLL_API __declspec(dllimport) 8 #endif 9 10 // 導出類 11 class DLL_API Cdll { 12 public: 13 Cdll(void); 14 // TODO: 在此添加您的方法。 15 }; 16 17 //導出變量,變量在.cpp文件中定義 18 extern DLL_API int ndll; 19 20 //導出函數,加extern "C",是為了保證編譯時生成的函數名不變,這樣動態調用dll時才能 21 //正確獲取函數的地址 22 extern "C" DLL_API int fndll(void);
dll.cpp 文件如下:
1 #include "dll.h" 2 3 4 // 這是導出變量的一個示例 5 DLL_API int ndll=6; 6 7 // 這是導出函數的一個示例。 8 DLL_API int fndll(void) 9 { 10 return 42; 11 } 12 13 // 這是已導出類的構造函數。 14 // 有關類定義的信息,請參閱 dll.h 15 Cdll::Cdll() 16 { 17 return; 18 }
有兩種方法調用動態庫,一種隱式鏈接,一種顯示鏈接。
調用動態庫:隱式鏈接
隱式鏈接 需要.h文件,dll文件,lib文件
(1)將dll放到工程的工作目錄
(2)設置項目屬性--vc++目錄--庫目錄為lib所在的路徑
(3)將lib添加到項目屬性--鏈接器--輸入--附加依賴項(或者直接在源代碼中加入#pragma comment(lib, “**.lib”))
(4)在源文件中添加.h頭文件
然后就像平常一樣調用普通函數、類、變量
調用動態庫:顯示鏈接
顯示鏈接 只需要.dll文件,但是這種調用方式不能調用dll中的變量或者類(其實可以調用類,但是相當麻煩,有興趣者可參考http://blog.csdn.net/jdcb2001/article/details/1394883)
顯示調用主要使用WIN32 API函數LoadLibrary、GetProcAddress,舉例如下:
1 typedef int (*dllfun)(void);//定義指向dll中函數的函數指針 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();
生成靜態庫
新建項目--win32項目--填寫項目名--確定--下一步--應用程序類型:選擇靜態庫
靜態庫項目沒有main函數,也沒有像dll項目中的dllmain。
創建項目后添加.h文件,添加相應的導出函數、變量或類,如下所示
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 }
編譯工程后就會生成一個.lib文件
需要.h文件,lib文件
(1)設置項目屬性--vc++目錄--庫目錄為lib所在的路徑
(2)將lib添加到項目屬性--鏈接器--輸入--附加依賴項(或者直接在源代碼中加入#pragma comment(lib, “**.lib”))
(3)在源文件中添加.h頭文件
然后就像平常一樣調用普通函數、類、變量,舉例如下:
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 }
【版權聲明】轉載請注明出處 http://www.cnblogs.com/TenosDoIt/p/3203137.html