lib 和 dll 的區別、生成以及使用詳解


【目錄】

lib dll介紹

生成動態庫

調用動態庫

生成靜態庫

調用靜態庫


 

首先介紹一下靜態庫(靜態鏈接庫)、動態庫(動態鏈接庫)的概念,首先兩者都是代碼共享的方式。

靜態庫在鏈接步驟中,連接器將從庫文件取得所需的代碼,復制到生成的可執行文件中,這種庫稱為靜態庫,其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗余拷貝。即靜態庫中的指令都全部被直接包含在最終生成的 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM