【C/C++】lib 和 dll 的区别、生成以及使用详解
?
VS開發多功能模塊的項目時,負責不同模塊的人員因為權限問題,不能拿到所有源碼,但又需要進行功能模塊的融合,這就需要使用dll、lib進行“代碼共享”。在學習dll和lib時,找到了篇講解十分詳細的博文,因此轉載供自己和更多的人學習,原文鏈接分享如下:http://www.cnblogs.com/TenosDoIt/p/3203137.html,感謝原博主的精心總結。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
首先介紹一下靜態庫(靜態鏈接庫)、動態庫(動態鏈接庫)的概念,首先兩者都是代碼共享的方式。
靜態庫:在鏈接步驟中,連接器將從庫文件取得所需的代碼,復制到生成的可執行文件中,這種庫稱為靜態庫,其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗余拷貝。即靜態庫中的指令都全部被直接包含在最終生成的 EXE 文件中了。在vs中新建生成靜態庫的工程,編譯生成成功后,只產生一個.lib文件
動態庫:動態鏈接庫是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬于其可執行代碼的函數。函數的可執行代碼位于一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接并與使用它們的進程分開存儲的函數。在vs中新建生成動態庫的工程,編譯成功后,產生一個.lib文件和一個.dll文件
那么上述靜態庫和動態庫中的lib有什么區別呢?
靜態庫中的lib:該LIB包含函數代碼本身(即包括函數的索引,也包括實現),在編譯時直接將代碼加入程序當中
動態庫中的lib:該LIB包含了函數所在的DLL文件和文件中函數位置的信息(索引),函數實現代碼由運行時加載在進程空間中的DLL提供
總之,lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。
以下例子均在vs2010上測試
一、生成和使用動態庫
1、生成動態庫
?新建項目--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_EXPORTS5 #define DLL_API __declspec(dllexport)6 #else7 #define DLL_API __declspec(dllimport)8 #endif9 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 }?
2、調用動態庫
有兩種方法調用動態庫,一種隱式鏈接,一種顯示鏈接。
調用動態庫:隱式鏈接
隱式鏈接 需要.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();?
二、生成和使用靜態庫
1、生成靜態庫
新建項目--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 testclass9 { 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文件
2、使用靜態庫
需要.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 }總結
以上是生活随笔為你收集整理的【C/C++】lib 和 dll 的区别、生成以及使用详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【VS2005】error LNK200
- 下一篇: 【C/C++】“std::basic_i