VS中動(dòng)態(tài)庫(kù)的創(chuàng)建和調(diào)用方式詳解
VS中動(dòng)態(tài)庫(kù)的創(chuàng)建和調(diào)用
庫(kù)
? 庫(kù)是寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼。庫(kù)的存在形式本質(zhì)上來(lái)說(shuō)庫(kù)是一種可執(zhí)行代碼的二進(jìn)制。
? 庫(kù)有兩種:靜態(tài)庫(kù)(.a、.lib)和動(dòng)態(tài)庫(kù)(.so、.dll)。所謂靜態(tài)、動(dòng)態(tài)是指鏈接階段,靜態(tài)庫(kù)的鏈接階段是在項(xiàng)目編譯的時(shí)候靜態(tài)鏈接。動(dòng)態(tài)庫(kù)是在程序運(yùn)行的時(shí)候由代碼加載鏈接。
? 靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的區(qū)別主要是在鏈接階段處理庫(kù)的方式不同而區(qū)分的。
靜態(tài)庫(kù)
概念
? 靜態(tài)庫(kù)指的是在鏈接階段直接將庫(kù)和目標(biāo)文件一起打包成可執(zhí)行文件的方式所使用的庫(kù)就稱為靜態(tài)庫(kù)。
體現(xiàn)形式
? .a 或者 .lib 文件
優(yōu)缺點(diǎn)
? 優(yōu)點(diǎn) :①使可執(zhí)行文件依賴項(xiàng)少,已經(jīng)被打包到可執(zhí)行文件中了。 ②編譯階段完成鏈接,執(zhí)行期間代碼裝載速度快
? 缺點(diǎn):①使可執(zhí)行文件變大。②若作為其他庫(kù)的依賴庫(kù),將會(huì)造成多余的副本,因?yàn)楸仨毰c目標(biāo)文件打包。③升級(jí)不方便,升級(jí)必須重新編譯
靜態(tài)庫(kù)的創(chuàng)建
- 使用VS創(chuàng)建一個(gè)空項(xiàng)目;
- 創(chuàng)建空項(xiàng)目之后將項(xiàng)目設(shè)置為靜態(tài)庫(kù)(點(diǎn)擊項(xiàng)目 -> 屬性 -> 常規(guī) -> 配置類型)中修改;
- 配置項(xiàng)目lib輸出位置(常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置);
- 書寫接口,在靜態(tài)庫(kù)中,只要是可以允許訪問(wèn)的函數(shù)和類都可以被使用,沒有特別的函數(shù)導(dǎo)入和導(dǎo)出。
例程:
#pragma once #include <iostream> class Arithmetic { public: // Returns a + b static double Add(double a, double b);//可以調(diào)用 // Returns a - b static double Subtract(double a, double b);//可以調(diào)用 // Returns a * b static double Multiply(double a, double b);//可以調(diào)用 // Returns a / b static double Divide(double a, double b);//可以調(diào)用 void fun2();//可以調(diào)用 private: static void fun();//不可以調(diào)用 void fun1();//不可以調(diào)用 };
#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)庫(kù)的調(diào)用
- 創(chuàng)建一個(gè)項(xiàng)目
- 配置項(xiàng)目屬性,導(dǎo)入靜態(tài)庫(kù)位置。
- 導(dǎo)入頭文件:C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
- 導(dǎo)入庫(kù)文件:鏈接器 -> 常規(guī)-> 附加庫(kù)目錄 :指的是在調(diào)用的時(shí)候聲名需要使用的lib文件。
- 添加導(dǎo)入lib名稱:鏈接器 -> 輸入 -> 附加依賴項(xiàng) :指的是在調(diào)用的時(shí)候聲名需要使用的lib文件。
- 引入庫(kù)的頭文件,之后直接使用庫(kù)即可。
動(dòng)態(tài)庫(kù)
概念
動(dòng)態(tài)庫(kù)指的是在程序運(yùn)行過(guò)程中動(dòng)態(tài)加載庫(kù)的方式使用的庫(kù),也就是動(dòng)態(tài)庫(kù)的鏈接是發(fā)生在程序運(yùn)行時(shí)期的,它和可執(zhí)行文件是分開的,只是可執(zhí)行文件在運(yùn)行的某個(gè)時(shí)期調(diào)用了它。
體現(xiàn)形式
? .DLL、.lib 和 .a 、.so ;
優(yōu)缺點(diǎn)
? 好處:程序自身的體積不會(huì)因?yàn)閯?dòng)態(tài)函數(shù)庫(kù)變大。
? 缺點(diǎn):就是程序運(yùn)行過(guò)程中使用到了這些函數(shù)庫(kù)內(nèi)的功能時(shí),萬(wàn)一系統(tǒng)特定的位置沒有對(duì)應(yīng)的動(dòng)態(tài)庫(kù)。就會(huì)造成程序崩潰或者各種奇怪的問(wèn)題。
動(dòng)態(tài)庫(kù)的創(chuàng)建
在介紹動(dòng)態(tài)庫(kù)的創(chuàng)建之前,我們先來(lái)了解以下的宏。
#pragma once #ifdef PUBFUN_EXPORTS #define PUBUTIL_DLL __declspec(dllexport) #else #define PUBUTIL_DLL __declspec(dllimport) #endif
MSVC編譯器提供了一系列C/C++的擴(kuò)展來(lái)指定符號(hào)的導(dǎo)入導(dǎo)出,即__declspec屬性關(guān)鍵字。
dllexport與dllimport存儲(chǔ)級(jí)屬性是微軟對(duì)C和C++的擴(kuò)展,可用于從dll中導(dǎo)入或?qū)С龊瘮?shù)、數(shù)據(jù)、對(duì)象(objects)
__declspec(dllexport) 表示該符號(hào)是從本DLL導(dǎo)出的符號(hào)。
__declspec(dllimport) 表示該符號(hào)是從別的DLL中導(dǎo)入的。
我們?cè)趧?chuàng)建動(dòng)態(tài)庫(kù)的時(shí)候需要用到上面的宏。
創(chuàng)建方式1:使用空項(xiàng)目
- 使用VS創(chuàng)建一個(gè)空項(xiàng)目;
- 創(chuàng)建空項(xiàng)目之后將項(xiàng)目設(shè)置為動(dòng)態(tài)庫(kù)(點(diǎn)擊項(xiàng)目 -> 屬性 -> 常規(guī) -> 配置類型)中修改;
- 配置項(xiàng)目lib 和 DLL 輸出位置(常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置);
- 創(chuàng)建一個(gè)header.h (此文件名可以自由定義)定義之后將上面的宏寫入到文件中(宏名稱可以自己定義)。
- 使用定義的宏定義動(dòng)態(tài)庫(kù)導(dǎo)出的函數(shù)或者類。
- 編譯生成動(dòng)態(tài)庫(kù)。
編譯生成動(dòng)態(tài)庫(kù)。
例程:
創(chuàng)建動(dòng)態(tài)庫(kù)導(dǎo)出導(dǎo)入宏
//header.h #pragma once #ifdef BD_TEST #define BDTEXT_DLL __declspec(dllimport) #else #define BDTEST_DLL __declspec(dllexport) #endif
使用宏定義導(dǎo)出的函數(shù)
//testDLL.h #pragma once #include "header.h" int BDTEXT_DLL add(int a, int b);
導(dǎo)出函數(shù)功能的實(shí)現(xiàn)
//testDLL.cpp #include "testDLL.h" int add(int a, int b) { return a + b; }
編譯:
這就是最后編譯出來(lái)的lib和dll庫(kù)。
創(chuàng)建方式2:直接創(chuàng)建動(dòng)態(tài)庫(kù)項(xiàng)目
使用直接創(chuàng)建動(dòng)態(tài)庫(kù)項(xiàng)目,會(huì)在項(xiàng)目中生成一個(gè)dllMain.cpp的文件。如下:
// dllmain.cpp : 定義 DLL 應(yīng)用程序的入口點(diǎn)。 #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; }
根據(jù)微軟官網(wǎng)說(shuō)明:
DllMain是動(dòng)態(tài)鏈接庫(kù) (DLL) 的可選入口點(diǎn)。 當(dāng)系統(tǒng)啟動(dòng)或終止進(jìn)程或線程時(shí),它將使用進(jìn)程的第一個(gè)線程為每個(gè)加載的 DLL 調(diào)用入口點(diǎn)函數(shù)。 使用 LoadLibrary 和 FreeLibrary 函數(shù)加載或卸載 DLL 時(shí),系統(tǒng)還會(huì)調(diào)用 DLL 的入口點(diǎn)函數(shù)。
之后其他的接口函數(shù)和接口類和空項(xiàng)目的建立是一樣的。
動(dòng)態(tài)庫(kù)的調(diào)用
- 創(chuàng)建一個(gè)項(xiàng)目
- 導(dǎo)入頭文件:C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
- 導(dǎo)入庫(kù)文件:鏈接器 -> 常規(guī)-> 附加庫(kù)目錄 :指的是在調(diào)用的時(shí)候聲名需要使用的lib文件。
- 添加導(dǎo)入lib名稱:鏈接器 -> 輸入 -> 附加依賴項(xiàng) :指的是在調(diào)用的時(shí)候聲名需要使用的lib文件。
- 引入庫(kù)的頭文件,之后直接使用庫(kù)即可。
- 將于lib配套的dll放到執(zhí)行文件exe所在的文件目錄下。
例程:
配置頭文件
配置lib文件位置
配置需要使用lib文件
配置完成之后編寫代碼
#include <iostream> #include <testDLL.h>//引入頭文件 int main() { std::cout << add(2, 5) << std::endl; //調(diào)用庫(kù)中的函數(shù) getchar(); return 0; }
注意點(diǎn):
1、沒有設(shè)置為導(dǎo)出的函數(shù)名稱或者類,無(wú)法在外部調(diào)用dll使用。導(dǎo)出的函數(shù)和類必須使用導(dǎo)出宏修飾。
項(xiàng)目常見配置項(xiàng)
常規(guī) -> 輸出目錄 :指的是dll輸出的文件位置
常規(guī) -> 中間目錄 :指的是中間件的輸出位置
常規(guī) -> 配置類型 :指的是項(xiàng)目類型
VC++目錄 -> 包含文件 :指的是三方庫(kù)文件的頭文件位置
VC++目錄 -> 庫(kù)目錄 : 指的是三方庫(kù)文件(.dll .lib)文件
C/C++ -> 常規(guī) -> 附加包含目錄 :指的是需要使用的自己編寫的頭文件
C/C++ -> 預(yù)處理器 -> 預(yù)處理器定義 : 指的是我們需要配置的宏定義
鏈接器 -> 輸入 -> 附加依賴項(xiàng) :指的是在調(diào)用的時(shí)候聲名需要使用的lib文件。
鏈接器 -> 高級(jí) -> 導(dǎo)入庫(kù) : 指的是lib導(dǎo)出的文件位置
到此這篇關(guān)于VS中動(dòng)態(tài)庫(kù)的創(chuàng)建和調(diào)用的文章就介紹到這了,更多相關(guān)VS動(dòng)態(tài)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Clion配置opencv開發(fā)環(huán)境的詳細(xì)過(guò)程
這篇文章主要介紹了Clion配置opencv開發(fā)環(huán)境的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考的下2022-04-04C++類的自動(dòng)轉(zhuǎn)換和強(qiáng)制類型轉(zhuǎn)換的實(shí)現(xiàn)示例
類的自動(dòng)轉(zhuǎn)換和強(qiáng)制類型轉(zhuǎn)換是面向?qū)ο缶幊讨刑幚眍愋椭g轉(zhuǎn)換的兩種重要機(jī)制,本文就來(lái)介紹一下這兩種方法的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07C++線程池的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了C++線程池的簡(jiǎn)單實(shí)現(xiàn)方法,包括了線程操作函數(shù)及相關(guān)屬性的用法,需要的朋友可以參考下2014-09-09Linux頁(yè)面置換算法的C語(yǔ)言實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Linux頁(yè)面置換算法的C語(yǔ)言實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12C++紅黑樹的底層實(shí)現(xiàn)機(jī)制詳解
紅黑樹與AVL樹一樣,也是一種自平衡的二叉搜索樹,它在每個(gè)結(jié)點(diǎn)上增加一個(gè)存儲(chǔ)位表示結(jié)點(diǎn)的顏色,可以是Red或Black,通過(guò)對(duì)任何一條從根到葉子的路徑上各個(gè)結(jié)點(diǎn)著色方式的限制,本文介紹了C++紅黑樹的底層實(shí)現(xiàn)機(jī)制,需要的朋友可以參考下2024-08-08C/C++語(yǔ)言中全局變量重復(fù)定義問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于C/C++語(yǔ)言中全局變量重復(fù)定義問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01C++ 基類指針和子類指針相互賦值的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇C++ 基類指針和子類指針相互賦值的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12