VS2019 使用 C/C++ 动态链接库 并 进行调用
?
vs2019生成dll并調(diào)用的實(shí)現(xiàn)示例:https://www.jb51.net/article/179759.htm
?
vs2017創(chuàng)建linux c++程序:https://blog.csdn.net/qingyulove/article/details/86659726
vs2019編寫Linux c/c++項(xiàng)目:https://blog.csdn.net/mmmsss987/article/details/103518996
Visual Studio 2019 基于Linux平臺(tái)的C++開發(fā):https://www.cnblogs.com/sgawscd/p/12916544.html
?
?
1. VS?中生成動(dòng)態(tài)鏈接庫(kù)的三種方式(導(dǎo)出函數(shù))
?
開發(fā)環(huán)境:VS2019
?
創(chuàng)建動(dòng)態(tài)鏈接庫(kù)項(xiàng)目
新建項(xiàng)目,搜索?DLL ,選擇 “?具有導(dǎo)出項(xiàng)的(DLL)動(dòng)態(tài)鏈接庫(kù) ”,
輸入項(xiàng)目名稱,選擇項(xiàng)目所在目錄,然后點(diǎn)擊 創(chuàng)建
生成如下圖所示的文件結(jié)構(gòu):
?
?
導(dǎo)出動(dòng)態(tài)鏈接庫(kù)
?
方法一 :聲明導(dǎo)出
?
1、以 C++ 的方式聲明導(dǎo)出。
在 CPP_DLL.cpp 文件中添加下面的函數(shù),在函數(shù)聲明前添加 _declspec(dllexport) 關(guān)鍵字
// C++ 的方式聲明導(dǎo)出 _declspec(dllexport) int addFunc(int a, int b); int addFunc(int a, int b) {return a + b; }示例截圖:
?
2、以 C 的方式聲明導(dǎo)出。
在 CPP_DLL.cpp 文件中添加下面的函數(shù),在函數(shù)聲明前添加 extern "C"? _declspec(dllexport) 關(guān)鍵字
// C 的方式聲明導(dǎo)出 extern "C" {_declspec(dllexport) int subFunc(int a, int b);int subFunc(int a, int b){return a + b;}}示例截圖:
然后點(diǎn)擊 “?生成解決方案 ” ,就可以在工程目錄的 debug 目錄或者 release 目錄下(這取決你生成的是debug版本還是release版本)生成了動(dòng)態(tài)鏈接庫(kù)的相關(guān)文件。第三方調(diào)用時(shí)關(guān)鍵的文件為 .lib文件 和 .dll文件 以及工程目錄下的 .h頭文件 。
?
?
方法二: 模塊定義文件導(dǎo)出
在項(xiàng)目中定義CPP_DLL.def 文件,該文件為模塊導(dǎo)出文件
在 CPP_DLL.cpp 文件中添加下面的函數(shù)
LIBRARY EXPORTSmulFuncdivFunc示例截圖:
?
如果是 VS 平臺(tái),必須要在 連接器 中添加 .def 文件
然后點(diǎn)擊 “?生成解決方案 ” ,就可以在工程目錄的 debug 目錄或者 release 目錄下(這取決你生成的是debug版本還是release版本)生成了動(dòng)態(tài)鏈接庫(kù)的相關(guān)文件。第三方調(diào)用時(shí)關(guān)鍵的文件為 .lib文件 和 .dll文件 以及工程目錄下的 .h頭文件 。
對(duì)應(yīng)?的?DLL?和?lib?文件
?
?
?
2. 調(diào)用前面開發(fā)的動(dòng)態(tài)鏈接庫(kù)
?
1. 新建一個(gè)C/C++項(xiàng)目(test)
?
?
2. 將第三方庫(kù)的 .h文件、.lib文件、.dll文件 復(fù)制進(jìn)工程項(xiàng)目中
? ? ? ? .dll文件是程序運(yùn)行需要載入的動(dòng)態(tài)鏈接庫(kù),VS中調(diào)試時(shí)可以通過 項(xiàng)目->屬性->調(diào)試->環(huán)境 欄目添加.dll文件的 path 而成功調(diào)試,但在獨(dú)立運(yùn)行.exe程序是須將.dll文件放到同一目錄下。
? ? ? ? 因此建議直接將 .dll文件 放入debug目錄下或release目錄下。.h頭文件 和 .lib庫(kù)文件 可以隨意放置,只要是能夠通過路徑找到即可,為了方便管理,建議建立文件夾,放置在項(xiàng)目目錄下。
?
?
3. 在項(xiàng)目中調(diào)用第三方庫(kù)
?
有三種方法可以調(diào)用第三方庫(kù)。
?
(1)直接在代碼前添加引用
因?yàn)橹苯右?CPPDLL.h?頭文件,所以需要把?動(dòng)態(tài)鏈接庫(kù)的?函數(shù)聲明放在頭文件中。
修改?CPP_DLL?的 .h?文件?和 cpp?文件,把?函數(shù)?聲明放在 .h?中,函數(shù)定義放在?cpp?文件中。
CPP_DLL.h
// C++ 的方式聲明導(dǎo)出 _declspec(dllexport) int addFunc(int a, int b);// C 的方式聲明導(dǎo)出 extern "C" {_declspec(dllexport) int subFunc(int a, int b); }int mulFunc(int a, int b); double divFunc(double a, double b);CPP_DLL.cpp
int addFunc(int a, int b) {return a + b; }int subFunc(int a, int b) {return a - b; }// def 文件形式 int mulFunc(int a, int b) {return a * b; }double divFunc(double a, double b) {return a / b; }重新生成?DLL?文件,并將?DLL? 、lib 、.h?文件拷貝到對(duì)應(yīng)目錄
?
C++?測(cè)試代碼:
#include <iostream> #include "./CPP_DLL.h" //通過相對(duì)路徑或絕對(duì)路徑添加頭文件 #pragma comment (lib,"./CPPDLL.lib") // 添加 lib 文件int main() {std::cout << "Hello World!\n";std::cout << addFunc(1, 2) << std::endl;std::cout << subFunc(3, 4) << std::endl;std::cout << mulFunc(5, 6) << std::endl;std::cout << divFunc(7, 8) << std::endl; }運(yùn)行結(jié)果截圖:
?
?
(2)在解決方案管理面板中添加頭文件和資源文件
添加一個(gè)現(xiàn)有項(xiàng)頭文件,在文件夾中找到第三方庫(kù)的頭文件( CPP_DLL.h ),添加進(jìn)新建立的項(xiàng)目。
添加一個(gè)現(xiàn)有項(xiàng)資源文件,在文件夾中找到第三方庫(kù)的庫(kù)文件( CPPDLL.lib ),添加進(jìn)新建立的項(xiàng)目。
?
?
(3)在 項(xiàng)目屬性 -> 設(shè)置 中 添加 頭文件 和 庫(kù)文件
- 項(xiàng)目->屬性->VC++目錄->包含目錄 中添加第三方庫(kù)的 頭文件;
- 庫(kù)目錄 下 添加 第三方庫(kù) 的 庫(kù)文件(.lib文件)。
- 項(xiàng)目->屬性->鏈接器->輸入->附加依賴項(xiàng)中輸入 庫(kù)文件名稱。
在函數(shù)中調(diào)用第三方庫(kù)中的函數(shù)
#include <iostream>int main() {std::cout << "Hello World!\n";std::cout << addFunc(1, 2) << std::endl;std::cout << subFunc(3, 4) << std::endl;std::cout << mulFunc(5, 6) << std::endl;std::cout << divFunc(7, 8) << std::endl; }?
?
4.?直接在代碼里 load 動(dòng)態(tài)庫(kù)dll文件即可
這種方法不需要 include .h文件,不需要添加 lib庫(kù) 和 lib庫(kù)路徑,
- 引入 windows.h(必須)
- 在 main 函數(shù)寫下列語句調(diào)用 dll
? ? ? ? 因?yàn)?C++?聲明?的?動(dòng)態(tài)鏈接庫(kù)會(huì)發(fā)生?Name Mangling,導(dǎo)致?編譯后的函數(shù)名字會(huì)發(fā)生變化,所以需要使用?工具?查看?編譯編譯后的?動(dòng)態(tài)鏈接庫(kù)?對(duì)應(yīng)的函數(shù)名。
? ? ? ? 而 extern "C"?聲明的?和?def?文件聲明的,編譯后的函數(shù)名不會(huì)發(fā)生變化,可以直接使用。
VS2019?自帶的工具?dumpbin.exe?可以查看編譯后的?動(dòng)態(tài)鏈接庫(kù)對(duì)應(yīng)的?函數(shù)名。
打開命令行,輸入命令?dumpbin -exports CPPDLL.dll
結(jié)果截圖:
所以?addFunc?不能直接使用,只能用被?name?Mangling 后的名字 ,這里? addFunc?編譯后的名字是??addFunc@@YAHHH@Z
示例程序代碼:
#include <iostream> #include <windows.h>// 加、減、乘 都是 int 類型 typedef int(*lpFunc)(int a, int b); //后邊為參數(shù),前面為返回值// 除法 是 double 類型 typedef double(*lpFuncD)(double a, double b); //后邊為參數(shù),前面為返回值int main() {std::cout << "Hello World!\n";HMODULE hModule;hModule = LoadLibrary(L"CPPDLL.dll"); //調(diào)用DLL lpFunc lpfunc = NULL;// GetProcAddress為獲取該函數(shù)的地址 // "?addFunc@@YAHHH@Z" 這個(gè)就是 C++ Name Mangling后的 addFunc 的函數(shù)名lpfunc = (lpFunc)GetProcAddress(hModule, "?addFunc@@YAHHH@Z");std::cout << lpfunc(1, 2) << std::endl;/* 使用 C extern 和 def 文件定義的動(dòng)態(tài)鏈接庫(kù),函數(shù)名不會(huì)發(fā)生變化 */lpfunc = (lpFunc)GetProcAddress(hModule, "subFunc");std::cout << lpfunc(3, 4) << std::endl;lpfunc = (lpFunc)GetProcAddress(hModule, "mulFunc");std::cout << lpfunc(5, 6) << std::endl;lpFuncD lpfuncd = NULL;lpfuncd = (lpFuncD)GetProcAddress(hModule, "divFunc");std::cout << lpfuncd(7, 8) << std::endl;//釋放FreeLibrary(hModule); }運(yùn)行結(jié)果:
?
?
方法 5:使用?lib?文件?和?dll?文件
- 把 CPPDLL.dll?文件放到?debug?目錄下,
- 然后在項(xiàng)目中引入?CPPDLL.lib?文件。 鏈接器 ->?輸入 ->?附加依賴項(xiàng) ->?編輯
示例代碼:
#include <iostream>// addFunc 是使用 C++ 方式聲明的, _declspec(dllimport) int addFunc(int a, int b);//subFunc 是 使用 extern "C" 聲明的 extern "C" _declspec(dllimport) int subFunc(int a, int b);// mulFunc 和 divFunc 是 使用 def 聲明的 _declspec(dllimport) int mulFunc(int a, int b); _declspec(dllimport) double divFunc(double a, double b);int main() {std::cout << "Hello World!\n";std::cout << addFunc(1, 2) << std::endl;std::cout << subFunc(3, 4) << std::endl;std::cout << mulFunc(5, 6) << std::endl;std::cout << divFunc(7, 8) << std::endl;return 0; }運(yùn)行結(jié)果:
還可以結(jié)合 第一種方法,使用??#pragma comment (lib,"./CPPDLL.lib") ?//添加?lib 文件?
這樣就不用?手動(dòng)設(shè)置?添加?lib?文件了
#include <iostream> #pragma comment (lib,"./CPPDLL.lib")// addFunc 是使用 C++ 方式聲明的, _declspec(dllimport) int addFunc(int a, int b); // 聲明 addFunc 函數(shù)//subFunc 是 使用 extern "C" 聲明的 extern "C" _declspec(dllimport) int subFunc(int a, int b); // 聲明 subFunc 函數(shù)// mulFunc 和 divFunc 是 使用 def 聲明的 _declspec(dllimport) int mulFunc(int a, int b); // 聲明 mulFunc 函數(shù) _declspec(dllimport) double divFunc(double a, double b); // 聲明 divFunc 函數(shù)int main() {std::cout << "Hello World!\n";std::cout << addFunc(1, 2) << std::endl;std::cout << subFunc(3, 4) << std::endl;std::cout << mulFunc(5, 6) << std::endl;std::cout << divFunc(7, 8) << std::endl;return 0; }?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的VS2019 使用 C/C++ 动态链接库 并 进行调用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全能终端神器 --- MobaXterm
- 下一篇: C++ AFX_MANAGE_STATE