VS中動態(tài)庫的創(chuàng)建和調用方式詳解
VS中動態(tài)庫的創(chuàng)建和調用
庫
? 庫是寫好的現有的,成熟的,可以復用的代碼。庫的存在形式本質上來說庫是一種可執(zhí)行代碼的二進制。
? 庫有兩種:靜態(tài)庫(.a、.lib)和動態(tài)庫(.so、.dll)。所謂靜態(tài)、動態(tài)是指鏈接階段,靜態(tài)庫的鏈接階段是在項目編譯的時候靜態(tài)鏈接。動態(tài)庫是在程序運行的時候由代碼加載鏈接。
? 靜態(tài)庫和動態(tài)庫的區(qū)別主要是在鏈接階段處理庫的方式不同而區(qū)分的。
靜態(tài)庫
概念
? 靜態(tài)庫指的是在鏈接階段直接將庫和目標文件一起打包成可執(zhí)行文件的方式所使用的庫就稱為靜態(tài)庫。
體現形式
? .a 或者 .lib 文件
優(yōu)缺點
? 優(yōu)點 :①使可執(zhí)行文件依賴項少,已經被打包到可執(zhí)行文件中了。 ②編譯階段完成鏈接,執(zhí)行期間代碼裝載速度快
? 缺點:①使可執(zhí)行文件變大。②若作為其他庫的依賴庫,將會造成多余的副本,因為必須與目標文件打包。③升級不方便,升級必須重新編譯
靜態(tài)庫的創(chuàng)建
- 使用VS創(chuàng)建一個空項目;
- 創(chuàng)建空項目之后將項目設置為靜態(tài)庫(點擊項目 -> 屬性 -> 常規(guī) -> 配置類型)中修改;
- 配置項目lib輸出位置(常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置);
- 書寫接口,在靜態(tài)庫中,只要是可以允許訪問的函數和類都可以被使用,沒有特別的函數導入和導出。
例程:
#pragma once #include <iostream> class Arithmetic { public: // Returns a + b static double Add(double a, double b);//可以調用 // Returns a - b static double Subtract(double a, double b);//可以調用 // Returns a * b static double Multiply(double a, double b);//可以調用 // Returns a / b static double Divide(double a, double b);//可以調用 void fun2();//可以調用 private: static void fun();//不可以調用 void fun1();//不可以調用 };
#include "Arithmetic.h" double Arithmetic::Add(double a, double b) { return a + b; } double Arithmetic::Subtract(double a, double b) { return a - b; } double Arithmetic::Multiply(double a, double b) { return a * b; } double Arithmetic::Divide(double a, double b) { return a / b; } void Arithmetic::fun2() { std::cout << "公共 void Arithmetic::fun2()" << std::endl; } void Arithmetic::fun() { std::cout << "私有 static void Arithmetic::fun()" << std::endl; } void Arithmetic::fun1() { std::cout << "私有 void Arithmetic::fun1()" << std::endl; }
靜態(tài)庫的調用
- 創(chuàng)建一個項目
- 配置項目屬性,導入靜態(tài)庫位置。
- 導入頭文件:C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
- 導入庫文件:鏈接器 -> 常規(guī)-> 附加庫目錄 :指的是在調用的時候聲名需要使用的lib文件。
- 添加導入lib名稱:鏈接器 -> 輸入 -> 附加依賴項 :指的是在調用的時候聲名需要使用的lib文件。
- 引入庫的頭文件,之后直接使用庫即可。
動態(tài)庫
概念
動態(tài)庫指的是在程序運行過程中動態(tài)加載庫的方式使用的庫,也就是動態(tài)庫的鏈接是發(fā)生在程序運行時期的,它和可執(zhí)行文件是分開的,只是可執(zhí)行文件在運行的某個時期調用了它。
體現形式
? .DLL、.lib 和 .a 、.so ;
優(yōu)缺點
? 好處:程序自身的體積不會因為動態(tài)函數庫變大。
? 缺點:就是程序運行過程中使用到了這些函數庫內的功能時,萬一系統(tǒng)特定的位置沒有對應的動態(tài)庫。就會造成程序崩潰或者各種奇怪的問題。
動態(tài)庫的創(chuàng)建
在介紹動態(tài)庫的創(chuàng)建之前,我們先來了解以下的宏。
#pragma once #ifdef PUBFUN_EXPORTS #define PUBUTIL_DLL __declspec(dllexport) #else #define PUBUTIL_DLL __declspec(dllimport) #endif
MSVC編譯器提供了一系列C/C++的擴展來指定符號的導入導出,即__declspec屬性關鍵字。
dllexport與dllimport存儲級屬性是微軟對C和C++的擴展,可用于從dll中導入或導出函數、數據、對象(objects)
__declspec(dllexport) 表示該符號是從本DLL導出的符號。
__declspec(dllimport) 表示該符號是從別的DLL中導入的。
我們在創(chuàng)建動態(tài)庫的時候需要用到上面的宏。
創(chuàng)建方式1:使用空項目
- 使用VS創(chuàng)建一個空項目;
- 創(chuàng)建空項目之后將項目設置為動態(tài)庫(點擊項目 -> 屬性 -> 常規(guī) -> 配置類型)中修改;
- 配置項目lib 和 DLL 輸出位置(常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置);
- 創(chuàng)建一個header.h (此文件名可以自由定義)定義之后將上面的宏寫入到文件中(宏名稱可以自己定義)。
- 使用定義的宏定義動態(tài)庫導出的函數或者類。
- 編譯生成動態(tài)庫。
編譯生成動態(tài)庫。
例程:
創(chuàng)建動態(tài)庫導出導入宏
//header.h #pragma once #ifdef BD_TEST #define BDTEXT_DLL __declspec(dllimport) #else #define BDTEST_DLL __declspec(dllexport) #endif
使用宏定義導出的函數
//testDLL.h #pragma once #include "header.h" int BDTEXT_DLL add(int a, int b);
導出函數功能的實現
//testDLL.cpp #include "testDLL.h" int add(int a, int b) { return a + b; }
編譯:
這就是最后編譯出來的lib和dll庫。
創(chuàng)建方式2:直接創(chuàng)建動態(tài)庫項目
使用直接創(chuàng)建動態(tài)庫項目,會在項目中生成一個dllMain.cpp的文件。如下:
// dllmain.cpp : 定義 DLL 應用程序的入口點。 #include "pch.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
根據微軟官網說明:
DllMain是動態(tài)鏈接庫 (DLL) 的可選入口點。 當系統(tǒng)啟動或終止進程或線程時,它將使用進程的第一個線程為每個加載的 DLL 調用入口點函數。 使用 LoadLibrary 和 FreeLibrary 函數加載或卸載 DLL 時,系統(tǒng)還會調用 DLL 的入口點函數。
之后其他的接口函數和接口類和空項目的建立是一樣的。
動態(tài)庫的調用
- 創(chuàng)建一個項目
- 導入頭文件:C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
- 導入庫文件:鏈接器 -> 常規(guī)-> 附加庫目錄 :指的是在調用的時候聲名需要使用的lib文件。
- 添加導入lib名稱:鏈接器 -> 輸入 -> 附加依賴項 :指的是在調用的時候聲名需要使用的lib文件。
- 引入庫的頭文件,之后直接使用庫即可。
- 將于lib配套的dll放到執(zhí)行文件exe所在的文件目錄下。
例程:
配置頭文件
配置lib文件位置
配置需要使用lib文件
配置完成之后編寫代碼
#include <iostream> #include <testDLL.h>//引入頭文件 int main() { std::cout << add(2, 5) << std::endl; //調用庫中的函數 getchar(); return 0; }
注意點:
1、沒有設置為導出的函數名稱或者類,無法在外部調用dll使用。導出的函數和類必須使用導出宏修飾。
項目常見配置項
常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置
常規(guī) -> 中間目錄 :指的是中間件的輸出位置
常規(guī) -> 配置類型 :指的是項目類型
VC++目錄 -> 包含文件 :指的是三方庫文件的頭文件位置
VC++目錄 -> 庫目錄 : 指的是三方庫文件(.dll .lib)文件
C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
C/C++ -> 預處理器 -> 預處理器定義 : 指的是我們需要配置的宏定義
鏈接器 -> 輸入 -> 附加依賴項 :指的是在調用的時候聲名需要使用的lib文件。
鏈接器 -> 高級 -> 導入庫 : 指的是lib導出的文件位置
到此這篇關于VS中動態(tài)庫的創(chuàng)建和調用的文章就介紹到這了,更多相關VS動態(tài)庫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Clion配置opencv開發(fā)環(huán)境的詳細過程
這篇文章主要介紹了Clion配置opencv開發(fā)環(huán)境的詳細過程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考的下2022-04-04