【08】C++實戰篇——C++ 生成動態庫.dll 及 C++調用DLL,及實際項目中的使用技巧

文章目錄

  • 一、創建動態庫dll (方法一)
    • 1 生成C++ 動態庫dll
      • 1.1 創建項目MyDLL
      • 1.2 編寫.h 和 .cpp文件
      • 1.3 設置 及 生成 DLL
    • 2 調用 C++ 動態庫dll
      • 2.1 創建C++ 空項目DLLtest
      • 2.2 動態庫配置 及代碼調用測試
    • 3 實際項目中的使用技巧
      • 3.1 設置dll輸出路徑
      • 3.2 設置頭文件引入路徑
      • 3.3 改進后 測試
    • 4 __cplusplus 解釋
    • 5 完整代碼.h文件、.cpp 文件
    • 6 完整項目文件下載

創建動態庫dll項目有兩種方法;

  • 1.VS創建 C++ 空項目,然后在項目屬性中將項目 配置類型 改為 動態庫(.dll),規范性要求不高,且創建方式熟悉。這種方法也可以用,但有時這種方法生成的dll在項目調用中, 會出現各種奇怪的錯誤。 故,此法 多用于新手測試,正式項目慎用。
  • 2.VS創建 動態鏈接庫(DLL) 項目, 更安全、正規,代碼要求更規范。

一、創建動態庫dll (方法一)

1 生成C++ 動態庫dll

為了驗證效果,使用三種方法導出函數:

  • //導出函數
  • //導出類
  • //以C方式導出函數
創建動態庫d11:1.VS創建動態鏈接庫(DLL) MyDLL:編寫.h和.cpp文件在.h文件中宏定義導出圖數2.生成dll文件:右鍵項目-->屬性-->配置類型-->動態庫( .dll)以Debug x64 生成解決方案

1.1 創建項目MyDLL

1.VS創建C++ 空項目MyDLL:
在這里插入圖片描述
在這里插入圖片描述

1.2 編寫.h 和 .cpp文件

添加 mathTest.hmathTest.cpp文件
在這里插入圖片描述
mathTest.h 文件

#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//導出函數
MATHTEST_API int add(int a, int b);//加法
MATHTEST_API int subtract(int a, int b);//減法//導出類
class MATHTEST_API mathTest
{public:int multiply(int a, int b);//乘法int divide(int a, int b);//除法
};//以C方式導出函數
//extern "C",告訴編譯器這里是C語言代碼//為了使自己建的庫可以在 C/C++ 通用調用,使用 __cplusplus ,
//當C++調用代碼時,__cplusplus 值為1,聲明函數外面就加了一層“extern "C" {}”;
//當C 調用代碼時,__cplusplus 值為0,就相當于沒有“extern "C" {}”;#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);//加法MATHTEST_API int Csubtract(int a, int b);//減法
#ifdef __cplusplus
}
#endif#endif

mathTest.cpp文件

#include "mathTest.h"/*創建動態庫d11:1.VS創建C++ 空項目MyDLL:編寫.h和.cpp文件在.h文件中宏定義導出圖數2.生成dll文件:右鍵項目-->屬性-->配置類型-->動態庫( .dll)以Debug x64 生成解決方案
*///導出函數
int add(int a, int b)//加法
{return a + b;
}
int subtract(int a, int b)//減法
{return a - b;
}//導出類
int mathTest::multiply(int a, int b)//乘法
{return a * b;
}int mathTest::divide(int a, int b)//除法
{return a / b;
}//以C方式導出函數
int Cadd(int a, int b)//加法
{return a + b;
}int Csubtract(int a, int b)//減法
{return a - b;
}

1.3 設置 及 生成 DLL

右鍵項目–>屬性–>配置類型–>動態庫( .dll)
在這里插入圖片描述
右鍵項目–>生成 (如修改后,可以點重新生成)
在這里插入圖片描述

在這里插入圖片描述

查看 生成的DLL文件
在這里插入圖片描述
查看DLL
在這里插入圖片描述

注意是.E:\Test\MyDLL\x64\Debug,在工程同級目錄下\x64\Debug下面

在這里插入圖片描述

而不是 E:\Test\MyDLL\MyDLL\x64\Debug,而不是在.h同級目錄的\x64\Debug下面(剛開始就在這里找,發現MyDLL.dll.recipe多了一個.recipe,迷糊了半天

在這里插入圖片描述

2 調用 C++ 動態庫dll

方法:

創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1..lib(MyDLL.lib).dll(MyDLL.d11).h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.lib3.#include mathTest.h4.代碼調用

2.1 創建C++ 空項目DLLtest

這里測試代碼有兩種建里新項目的方法:

  • 1可以直接在 "MyDLL”解決方案下 建創建C++ 空項目DLLtest;( 實際項目中dll項目和用戶項目建立在同一個解決方案下,這樣更方便代碼修改與管理,在調試時 主項目代碼還可以直接調試訪問dll中的源代碼,這樣就更方便dll代碼的調試優化等操作。)
  • 2 也單獨建立一個項目方案;

這里為了方便,直接原來的解決方案上新增測試項目這樣做的好處是如果測試之后dll代碼有問題或功能達不到預期,可以方便隨時修改dll的源代碼。

右鍵 解決方案"MyDLL”->添加->新建項目;創建C++ 空項目DLLtest

在這里插入圖片描述

在這里插入圖片描述
可以看到,解決方案下有兩個項目,“DLLtest”和“MyDLL
在這里插入圖片描述
在DLLtest項目下添加,main.cpp文件
在這里插入圖片描述

2.2 動態庫配置 及代碼調用測試

使用動態庫d11:
隱式調用:

   隱式調用:1.把.lib(MyDLL.lib)、.dll(MyDLL.dll)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.lib3.#include mathTest.h4.代碼調用

在這里插入圖片描述
在我們的dll文件中分別設置了 導出函數、導出類成員函數、以C方式導出的函數,現在這三種函數都在main文件中調用測試。

完整代碼

#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.1b3.#include mathTest.h4.代碼調用
*/int main()
{//調用dll 導出函數int sum = add(10, 5);int sub = subtract(10, 5);//調用dll 導出類成員函數mathTest mathT; //實例化對象int mul = mathT.multiply(10, 5);int div = mathT.divide(10, 5);//調用dll 以C方式導出的函數int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);cout << "我的動態庫dll調用: "<< endl;cout << "add(10,5) = " << sum << endl<< "subtract(10,5) = " << sub << endl<< "multiply(10,5) = " << mul << endl<< "divide(10,5) = " << div << endl<< "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl;return 0;
}

運行測試,報錯。是因為 當前啟動項為“MyDLL”,需要將啟動項設為 “DLLtest”。
在這里插入圖片描述
右鍵 “DLLtest”,選擇“設為啟動項”
在這里插入圖片描述

在這里插入圖片描述
導出函數、導出類成員函數、以C方式導出的函數,現在這三種函數都用結果都輸出了,說明這三種dll導出函數方式都有,但我最常用的是 以C方式導出的函 ,這中通用個,避免出錯。

在這里插入圖片描述

3 實際項目中的使用技巧

自動路徑(.dll、.lib、.h復制到 測試項目的.cpp目錄下,太麻煩)

3.1 設置dll輸出路徑

直接將dll生成文件,的生路徑設為 “DLLtest”項目下的.cpp路徑;

打開項目,觀察路徑位置關系
在這里插入圖片描述

為了是的路徑通用,這里使用相對路徑 ../DLLtest/,并且將 MyDLL設為啟動項,方便后面dll重新生成
在這里插入圖片描述
重新生成dll,可見新的dll文件已經 生成在DLLtest項目下面了
在這里插入圖片描述
在這里插入圖片描述

3.2 設置頭文件引入路徑

將DLLtest設為啟動項;
設置DLLtest項目的 附加包含目錄為 …/MyDLL/這樣DLLtest項目就可以訪問 mathTest.h 文件了。
在這里插入圖片描述

3.3 改進后 測試

在這里插入圖片描述

注意:既然新的dll生成路徑已經更改到 “DLLtest”項目下的.cpp路徑,那么第一次在 MyDLL\x64\Debug\路徑下生成的生成的dll最好刪掉,

不然兩個路徑同時存在dll,調用時會產生混淆,當兩個路徑下的dll代碼源文件完全一樣時,似乎并沒有影響。一旦新的dll代碼修改了,這時兩個路徑下dll內容不一致,調用運行時就會出錯。

所以下面的4文件刪掉。
在這里插入圖片描述

4 __cplusplus 解釋

為了使自己建的 C/C++ 庫可 都可以通用

使用 __cplusplus

  • 當C++代碼時,__cplusplus 值為1;
  • 當C 代碼時,__cplusplus 值為0;
#ifdef __cplusplus 
.
.
.
#endif

下面是完整的.h文件

//#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//動態鏈接MATHTEST_API庫//以C語言的方式導出函數
//extern "C",告訴編譯器這里是C語言代碼#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法#ifdef __cplusplus
}
#endif#endif

當C++ 代碼時,__cplusplus 值為1,那么源代碼對應部分 等價于

extern "C"
{MATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法
}
#endif

當C 代碼時,__cplusplus 值為0,那么源代碼 對應部分 等價于;
#ifdef __cplusplus#endif 部分是沒有執行的

	MATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法

5 完整代碼.h文件、.cpp 文件

為了統一規范,同時使用“以C語言的方式導出函數”

mathTest.h文件

#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//以C方式導出函數
//extern "C",告訴編譯器這里是C語言代碼//為了使自己建的庫可以在 C/C++ 通用調用,使用 __cplusplus ,
//當C++調用代碼時,__cplusplus 值為1,聲明函數外面就加了一層“extern "C" {}”;
//當C 調用代碼時,__cplusplus 值為0,就相當于沒有“extern "C" {}”;#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法#ifdef __cplusplus
}
#endif#endif

mathTest.cpp文件

#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.1b3.#include mathTest.h4.代碼調用
*/int main()
{//調用以C方式導出的函數int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);int Cmul = Cmultiply(10, 5);int Cdiv = Cdivide(10, 5);cout << "我的動態庫dll調用: " << endl;cout << "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl<< "Cmultiply(10,5) = " << Cmul << endl<< "Cdivide(10,5) = " << Cdiv << endl;return 0;
}

6 完整項目文件下載

完整項目工程文件,下載后可直接編譯運行
在這里插入圖片描述

代碼下載:C++ 生成動態庫.dll 及 C++調用DLL

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91978.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91978.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91978.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kettle插件-kettle http client plus插件,輕松解決https接口無法調用文件流下載問題

場景&#xff1a;小伙伴在使用kettle調用https接口過程中無法正常調用&#xff0c;程序出錯問題&#xff0c;今天演示下用自研插件輕松解決這個問題。1、使用openssl 生成自簽名證書openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 3652、使用…

C#中的除法

在C#中&#xff0c;除法操作可以通過使用 / 運算符執行。這個運算符可以進行整數除法或浮點除法&#xff0c;這取決于操作數的類型。整數除法當兩個整數相除時&#xff0c;結果將自動向下取整到最接近的整數。這意味著結果是一個整數&#xff0c;而不是小數。int a 10; int b …

PPT文件密碼解密工具推薦:Tenorshare PassFab for PPT綠色免安裝一鍵解除密碼限制,附詳細教程和下載地址

前段時間&#xff0c;我幫朋友做一個商業演示的 PPT&#xff0c;為了防止文件被誤操作或者內容泄露&#xff0c;我給 PPT 設置了密碼。結果等朋友來拿文件的時候&#xff0c;我居然把密碼忘得干干凈凈&#xff0c;這下可把我倆都急壞了。朋友那邊馬上就要用這個 PPT 去參加重要…

【數據結構】二叉樹接口實現指南:遞歸方法的高效運用 (附經典算法OJ)

文章目錄 1、前置說明 1、定義二叉樹結點結構 2、創建新節點 3、手動創建二叉樹 2、二叉樹的遍歷 1、前序&#xff0c;中序和后序遍歷 1.1、二叉樹前序遍歷 1.2、二叉樹中序遍歷 1.3、二叉樹后序遍歷 2、二叉樹層序遍歷 3、二叉樹的基礎操作 1、二叉樹節點總數 2、…

自動駕駛控制算法——LQR控制算法

自動駕駛控制算法——LQR控制算法 文章目錄自動駕駛控制算法——LQR控制算法**一、LQR 是什么&#xff1f;**二、LQR 原理2.1 線性狀態空間模型 (State–Space Model)2.2 二次型性能指標 JJJ2.3 代數黎卡提方程 (ARE)2.4 特點總結2.5 一句話總結 LQR 原理&#xff1a;2.5.1 場景…

Jotai:React輕量級原子化狀態管理,告別重渲染困擾

簡介 Jotai 是一個為 React 提供的原子化狀態管理庫&#xff0c;采用自下而上的方法來進行狀態管理。Jotai 受 Recoil 啟發&#xff0c;通過組合原子來構建狀態&#xff0c;并且渲染基于原子依賴性進行優化。這解決了 React 上下文的額外重新渲染問題&#xff0c;并消除了對 m…

C語言數據結構(7)貪吃蛇項目2.貪吃蛇項目實現

8. 核心邏輯實現分析 8.1 游戲主邏輯 程序開始就設置程序支持本地模式&#xff0c;然后進入程序的主邏輯。 主邏輯分為3個過程&#xff1a; ? 游戲開始&#xff08;GameStart&#xff09;完成游戲的初始化。 ? 游戲運行&#xff08;GameRun&#xff09;完成游戲運行邏輯的…

知識蒸餾 - 最小化KL散度與最小化交叉熵是完全等價的

知識蒸餾 - 最小化KL散度與最小化交叉熵是完全等價的 flyfish KL散度與交叉熵的數學關系 對于兩個概率分布 PPP&#xff08;真實分布&#xff09;和 QQQ&#xff08;模型預測分布&#xff09;&#xff0c;KL散度的定義是&#xff1a; DKL(P∥Q)∑xP(x)log?(P(x)Q(x)) D_{KL}(P…

設計心得——網絡包的處理

一、介紹 在程序的開發中&#xff0c;網絡開發是一個重要的應用場景。畢竟這些年IT行業之所以火&#xff0c;主要還是互聯網&#xff08;移動互聯網&#xff09;帶來的。網絡開發&#xff0c;有各種平臺、框架以及系統和庫提供的API&#xff0c;如果說網絡開發是一個特別復雜和…

sqli-labs通關筆記-第30關GET字符注入(WAF繞過 雙引號閉合 手工注入+腳本注入兩種方法)

目錄 一、源碼分析 1、index.php代碼審計 2、login.php代碼審計 3、java_implimentation函數 4、whitelist函數 5、SQL安全性分析 二、滲透實戰 1、進入靶場 2、WAF探測 &#xff08;1&#xff09;觸發WAF &#xff08;2&#xff09;繞過WAF 3、手工注入 &#xf…

【openlayers框架學習】九:openlayers中的交互類(select和draw)

文章目錄openlayers進階28 openlayers中的事件29 openlayers中select交互類的使用30 openlayers中select常見的配置選項31 openlayers中繪制交互類&#xff08;Draw&#xff09;openlayers進階 28 openlayers中的事件 常用進行事件交互的對象&#xff1a;map\view\source29 o…

Java企業級應用性能優化實戰

在企業級Java應用開發中,性能優化是確保系統穩定運行的關鍵因素。本文將從多個維度深入分析Java應用性能瓶頸,并提供實戰優化方案。 ?? 性能優化核心領域 1. 對象操作性能優化 在企業應用中,對象拷貝是一個高頻操作,特別是在分層架構中的DO、DTO、VO轉換。選擇合適的拷…

LLM Prompt與開源模型資源(3)如何寫一個好的 Prompt

學習材料&#xff1a;https://www.hiascend.com/developer/courses/detail/1935520434893606913 &#xff08;3.5&#xff09;學習時長&#xff1a; 預計 60 分鐘學習目的&#xff1a; 了解提示工程的定義與作用熟悉提示工程的關鍵技術相關概念掌握基于昇騰適配的大模型提示工程…

日志管理工具 ——ELK Stack

一、ELK Stack 概述1.1 核心組件ELK Stack&#xff08;現更名為 Elastic Stack&#xff09;是一套開源的日志收集、存儲、分析和可視化平臺&#xff0c;由三個核心組件構成&#xff1a;Elasticsearch&#xff1a;分布式搜索引擎&#xff0c;負責日志數據的存儲、索引和快速查詢…

SpringAI:AI工程應用框架新選擇

Spring AI 是一個用于 AI 工程的應用框架 Spring AI 是一個用于 AI 工程的應用框架。其目標是將可移植性和模塊化設計等 Spring 生態系統設計原則應用于 AI 領域,并推廣使用 POJO 作為應用程序的構建塊到 AI 領域。 Spring AI 的核心是解決 AI 集成的基本挑戰:將企業數據和…

Kettle 開源ETL數據遷移工具從入門到實戰

ETL&#xff08;Extract, Transform, Load&#xff09;工具是用于數據抽取、轉換和加載的軟件工具&#xff0c;用于支持數據倉庫和數據集成過程。Kettle作為傳統的ETL工具是純 java 開發的開源的 ETL工具&#xff0c;用于數據庫間的數據遷移 。可以在 Linux、windows、unix 中運…

Maven中的bom和父依賴

maven最全避坑指南寫完后&#xff0c;發現自己對于bom和父pom的理解還是不夠深入&#xff0c;特此轉載DeepSeek的回答&#xff0c;和大家一起學習了。 在 Maven 的依賴管理中&#xff0c;父 POM (Parent POM) 和 BOM (Bill of Materials) 都是用于實現集中化管理和控制的核心機…

Python 操作 Word 文檔:主流庫對比與選擇指南

在辦公自動化、報告生成、數據處理等領域&#xff0c;利用 Python 程序化地創建、讀取或修改 Microsoft Word 文檔 (.docx 格式) 是一項非常實用的技能。Python 生態中有多個優秀的庫可以完成這項任務&#xff0c;但它們各有側重和優缺點。選擇哪一個“最好用”&#xff0c;關鍵…

怎么修改論文格式呢?提供一份論文格式模板

注!!!本文內容是作者自己整理的一份模板,僅供參考,各位如何修改,還需要看學校的要求。 一、參考文獻 1、有一定數量的近幾年參考文獻、不宜過多中文文獻 英文期刊模板 [1] Taesoo K, Sooyoung K, Kyunghan L, et al. Special issue on 6G and satellite communication…

MVC 發布

MVC 發布 引言 MVC(Model-View-Controller)模式是一種廣泛應用于軟件開發的架構模式。它將應用程序分為三個主要部分:模型(Model)、視圖(View)和控制器(Controller)。這種模式不僅提高了代碼的可維護性和可擴展性,而且使得開發者可以更加專注于各個組件的開發。本文…