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