1. 程式人生 > >windows下lib 和 dll 的區別、生成以和使用詳解

windows下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標頭檔案

然後就像平常一樣呼叫普通函式、類、變數

呼叫動態庫:顯示連結

顯示呼叫主要使用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 }
複製程式碼