封裝動態庫dll與靜態庫lib(原理及簡單例項)

項雲發表於2020-12-28

開發流程

https://www.runoob.com/w3cnote/cpp-static-library-and-dynamic-library.html

lib、dll介紹

靜態庫:

在連結步驟中,聯結器將從庫檔案取得所需的程式碼,複製到生成的可執行檔案exe中,這種庫稱為靜態庫,其特點是可執行檔案中包含了庫程式碼的一份完整拷貝;缺點就是被多次使用就會有多份冗餘拷貝。即靜態庫中的指令都全部被直接包含在最終生成的 EXE 檔案中了。在vs中新建生成靜態庫的工程,編譯生成成功後,只產生一個.lib檔案

lib=>exe

靜態編譯\動態編譯

靜態庫lib編譯的時候全部嵌入exe,導致exe會很大

動態庫:

動態連結庫是一個包含可由多個程式同時使用的程式碼和資料的庫,DLL不是可執行檔案。動態連結提供了一種方法,使程式可以呼叫不屬於其可執行程式碼的函式。函式的可執行程式碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、連結並與使用它們的程式分開儲存的函式。在vs中新建生成動態庫的工程,編譯成功後,產生一個.lib檔案和一個.dll檔案。

動態庫就是動態載入

photoshop.exe 113MB

動態載入,用的時候連結一下

軟體升級,連一下網路,替換一下dll

靜態庫和動態庫中的lib有什麼區別呢?

1、靜態庫中的lib:該LIB包含函式程式碼本身(即包括函式的索引,也包括實現),在編譯時直接將程式碼加入程式當中

2、動態庫中的lib:該LIB包含了函式所在的DLL檔案和檔案中函式位置的資訊(索引),函式實現程式碼由執行時載入在程式空間中的DLL提供

總之,lib是編譯時用到的,dll是執行時用到的。如果要完成原始碼的編譯,只需要lib;如果要使動態連結的程式執行起來,只需要dll

生成和使用靜態庫lib

​ 1、建立win32專案、空專案、lib檔案

  • 建立testlib.h檔案

    #ifndef TETLIB_H
    #define TESTLB_H
    //防止標頭檔案重複包含
    //條件編譯指令
    
    //加減乘除,此處宣告想用函式
    int add(int a,int b);
    int Cheng(int a, int b);
    
    #endif
    
  • 建立testlib.cpp檔案

    #include "testlib.h"
    
    //加減乘除
    int add(int a, int b)
    {
    	return a + b;
    }
    
    int Cheng(int a, int b)
    {
    	return a*b;
    }
    
    

    2、建立win32控制檯程式、空專案(最下面的取消勾選)、控制檯程式

    #include <iostream>
    #include <stdio.h>
    #include "../testlib/testlib.h"               //包含靜態庫的標頭檔案
    #pragma comment(lib, "testlib.lib")           //連結靜態庫
    
    int main()
    {
    	std::cout << "請輸入兩個整數,計算和" << std::endl;
    	int a, b;
    	std::cin >> a >> b;
    
    	//呼叫靜態庫
    	std::cout << add(a, b) << std::endl;
    	std::cout << Cheng(a, b) << std::endl;
    	return 0;
    }
    

    1、包含靜態庫標頭檔案

    2、在聯結器-常規-附加庫目錄,包含lib — 相對路徑==…\Debug與$(SolutionDir)Debug一樣==

    3、#pragma comment(lib, “testlib.lib”) //連結靜態庫

生成和使用動態庫

1、建立win32專案、空專案(不勾選安全開發週期)、dll

  • 建立testdll.h檔案

    #ifndef TESDLL_H
    #define TESDLL_H
    
    //#ifdef和ifndef意思相反
    
    //條件編譯指令    如果預處理命令中有_DLLAPI,便執行export輸出,否則輸入
    #ifdef _DLLAPI           //**本win32專案下前處理器加入_DLLAPI**//
    #define DLLAPI _declspec(dllexport)
    #else
    #define DLLAPI _declspec(dllimport)
    #endif
    
    //宣告匯出函式
    extern "C"  DLLAPI int  /*DLLAPI*/ add(int a, int b); 
    //按著C語言的方式編譯,函式名稱不變,配合Dependency Walker軟體使用,可以很
    //直觀看出來。
    
    #endif
    
  • 建立testdll.cpp檔案

    #include "testdll.h"
    #include <iostream>
    
    int add(int a, int b)
    {
    	return a + b;
    }
    

2、建立win32控制檯程式、空專案、控制檯程式

  • 建立test.cpp檔案

    #include<iostream>
    #include"../testdll/testdll.h"
    //#pragma comment(lib,"testdll.lib")//這不是真的靜態庫,隱式呼叫
    
    //匯入,不叫匯出
    DLLAPI int add(int a, int b);
    
    
    int main()
    {
    	int a, b;
    	std::cout << "請輸入" << std::endl;
    	std::cin >> a >> b;
    
    	std::cout << add(a, b) << std::endl;
    
    	return 0;
    }
    

實現流程(隱式呼叫)

  • #include"…/testdll/testdll.h"的效果與在VC++目錄-包含目錄下新增效果一致
  • lib檔案應在聯結器-常規-附加庫目錄新增路徑
  • #pragma comment(lib,“testdll.lib”) 的效果與在連結器-輸入-附屬依賴項裡面加testdll.lib效果一致
  • ==dll的操作:==1、放到exe檔案下

​ 2、編寫出口和介面包含庫.h輸出測試檔案.cpp接收

//匯出
extern "C"  DLLAPI int  /*DLLAPI*/ add(int a, int b);
//匯入,不叫匯出
DLLAPI int add(int a, int b);
  • dll的操作另一種方式==(但是呼叫不會搞,呼叫好像有問題)==
建立模組元件 實際程式碼

實現流程(顯式呼叫)

瞭解,一般不常用,需要.h和dll,不需要lib

相關文章