当前位置:首页 » 《随便一记》 » 正文

CLR 尝试 C# 调用 C++ 的方法和类 Visual Studio 2019 (2022年3月详细记录)

2 人参与  2022年11月09日 12:41  分类 : 《随便一记》  评论

点击全文阅读


C# 调用 C++ 测试

0. 准备工作

测试平台:Visual Studio 2019操作系统:Windows 10 专业版CLR: Common Language RuntimeCLI: Common Language Infrastructure

开启 Visual Studio 新建解决方案 CsInvokeCppTest
在这里插入图片描述

同时产生一个 C# 控制台应用程序: CsInvokeCppTest,代码文件为 Program.cs
在这里插入图片描述

目标框架:.NET 5.0
在这里插入图片描述

(注意:这里的 C# 项目的框架版本,需要和后面 C++ 的框架版本一致)

1. 创建需要被调用的 C++ 方法

新建一个 C++ 空项目,这个项目中存放我们需要调用的方法
在这里插入图片描述

比如这里我们新建一个 Calculator 项目,新建两个类 BasicCal 和 AdvCal,分别放基础的运算和高阶运算方法(这里注意,我们的运算函数并不是这两个类的成员函数,这里仅仅是放在两个文件中用于演示)

然后在 .cpp 文件中实现运算函数

BasicCal.h 代码:

#pragma once#include <stdio.h>#include <stdlib.h>#include <iostream>// 编译器通过查看 CaculateDLL_EXPORTS 宏是否定义,来确定该源文件来自 DLL 文件还是外部程式。 #ifdef CaculateDLL_EXPORTS#define Calculator_DECLSPEC __declspec(dllexport)#else#define Calculator_DECLSPEC __declspec(dllimport)#endifextern "C" Calculator_DECLSPEC int Add(int numberA, int numberB);extern "C" Calculator_DECLSPEC int Subtract(int numberA, int numberB);extern "C" Calculator_DECLSPEC int Multiplication(int numberA, int numberB);extern "C" Calculator_DECLSPEC  int Divided(int numberA, int numberB);class BasicCal{public:BasicCal();~BasicCal();};

AdvCal.h 代码:

#pragma once#include <stdio.h>#include <stdlib.h>#include <iostream>// 编译器通过查看 CaculateDLL_EXPORTS 宏是否定义,来确定该源文件来自 DLL 文件还是外部程式。 #ifdef CaculateDLL_EXPORTS#define Calculator_DECLSPEC __declspec(dllexport)#else#define Calculator_DECLSPEC __declspec(dllimport)#endifextern "C" Calculator_DECLSPEC long double Power(int numberA, int numberB);extern "C" Calculator_DECLSPEC double Sqrt(int numberA);class AdvCal{AdvCal();~AdvCal();};

GetValue.h代码:

#pragma once#include <string>#include <iostream>#include <stdio.h>// 编译器通过查看 CaculateDLL_EXPORTS 宏是否定义,来确定该源文件来自 DLL 文件还是外部程式。 #ifdef CaculateDLL_EXPORTS#define Calculator_DECLSPEC __declspec(dllexport)#else#define Calculator_DECLSPEC __declspec(dllimport)#endifclass Calculator_DECLSPEC GetValue{public:GetValue(void);GetValue(int intTest);~GetValue(void);public:int GetIntValue();private:int intValue;};

BasicCal.cpp 代码:

#include "BasicCal.h"BasicCal::BasicCal(){}BasicCal::~BasicCal() {}Calculator_DECLSPEC int Add(int numberA, int numberB){return numberA + numberB;}Calculator_DECLSPEC int Subtract(int numberA, int numberB){return numberA - numberB;}Calculator_DECLSPEC int Multiplication(int numberA, int numberB){return numberA * numberB;}Calculator_DECLSPEC  int Divided(int numberA, int numberB){if (numberB == 0) {std::cout << "除数不能为空" << std::endl;}return numberA / numberB;}

AdvCal.cpp 代码:

#include "AdvCal.h"#include <iostream>#include <math.h>AdvCal::AdvCal(){}AdvCal::~AdvCal(){}Calculator_DECLSPEC long double Power(int numberA, int numberB){return pow(numberA, numberB);}Calculator_DECLSPEC double Sqrt(int numberA){return sqrt(numberA);}

GetValue.cpp 代码:

#include "GetValue.h"#include <string>#include <iostream>#include <stdio.h>GetValue::GetValue(){}GetValue::GetValue(int intTest){GetValue::intValue = intTest;}GetValue::~GetValue(){}int GetValue::GetIntValue(){return intValue;}

右键点击项目名称,修改属性:

配置管理器————活动解决方案平台————x64
在这里插入图片描述

常规————输出目录————F:\repos\CsInvokeCppTest\bin\Debug\net5.0

(注意:这里要看 C# 编译所使用的是哪个目录)

常规————配置类型————动态库(.dll)
在这里插入图片描述

C/C++————预处理器————添加 CaculateDLL_EXPORTS
在这里插入图片描述

这就完成了设定宏 CaculateDLL_EXPORTS,这时 CaculateDLL_EXPORTS 变为紫色
在这里插入图片描述

在 if else 语句作用下使得 Calculator_DECLSPEC 被定义为 __declspec(dllexport)

右键点击 Calculator————生成
在这里插入图片描述

进入输出目录可以看到生成的 Calculator.dll 文件

2. 实现 CLR

在解决方案下创建 CLR 空项目:ClrDll
在这里插入图片描述

(如果创建 CLR 的选项,说明 visual studio 安装的时候缺少了对应的模块,打开 vs 安装程序,选择 “使用C++的桌面开发”,这里点击一次会去掉勾选,点击两次会再次勾选,这时候看右边的可选项,里面有 “对v142生成工具的C++/CLI支持”,对其进行勾选,然后安装即可)

右键点击项目名称,修改属性:

VC++目录————库目录————F:\repos\CsInvokeCppTest\bin\Debug\net5.0
在这里插入图片描述

(该目录为 Calculator.dll 所在目录)

链接器————输入————附加依赖项————添加 Calculator.lib
在这里插入图片描述

添加 InvokeCpp 类

在 InvokeCpp.h 头文件中,#include AdvCal.h BasicCal.h GetValue.h

(这里相当于把 AdvCal 和 BasicCal 中的方法都包一层便于调用)

InvokeCpp.h 代码:

#pragma once#include <iostream>#include "F:\\repos\\Calculator\\BasicCal.h"#include "F:\\repos\\Calculator\\AdvCal.h"#include "F:\\repos\\Calculator\\GetValue.h"public ref class InvokeCpp{public:InvokeCpp();InvokeCpp(int value);int intValue;int AddCpp(int numberA, int numberB);int SubtractCpp(int numberA, int numberB);int MultiplicationCpp(int numberA, int numberB);int DividedCpp(int numberA, int numberB);long double PowerCpp(int numberA, int numberB);double SqrtCpp(int numberA);int GetIntCpp();};

InvokeCpp.cpp 代码:

#include "InvokeCpp.h"InvokeCpp::InvokeCpp(){}InvokeCpp::InvokeCpp(int value){intValue = value;}int InvokeCpp::AddCpp(int numberA, int numberB){return Add(numberA, numberB);}int InvokeCpp::SubtractCpp(int numberA, int numberB){return Subtract(numberA, numberB);}int InvokeCpp::MultiplicationCpp(int numberA, int numberB){return Multiplication(numberA, numberB);}int InvokeCpp::DividedCpp(int numberA, int numberB){return Divided(numberA, numberB);}long double InvokeCpp::PowerCpp(int numberA, int numberB){return Power(numberA, numberB);}double InvokeCpp::SqrtCpp(int numberA){return Sqrt(numberA);}int InvokeCpp::GetIntCpp(){GetValue GetClass(intValue);return GetClass.GetIntValue();}

右键点击 ClrDll————生成
在这里插入图片描述

在 F:\repos\CsInvokeCppTest\bin\Debug\net5.0\ 目录下会出现 ClrDll.dll
在这里插入图片描述

(注意,这里的输出目录虽然是默认的 F:\repos\CsInvokeCppTest\x64\Debug,但是在目标目录 F:\repos\CsInvokeCppTest\bin\Debug\net5.0\ 下也会出现编译完成的 ClrDll.dll)

3. 使用 C# 调用方法

Program.cs 代码:

using System;namespace CsInvokeCppTest{    class Program    {        public static void Main(string[] args)        {            try            {                Console.WriteLine("---------c# 通过 CLI 调用 C++ 方法---------");                Console.Write("请输入numberA:");                int numberA = Convert.ToInt32(Console.ReadLine());                Console.Write("请输入numberB:");                int numberB = Convert.ToInt32(Console.ReadLine());                Console.Write("请输入numberC:");                int numberC = Convert.ToInt32(Console.ReadLine());                InvokeCpp invoke = new InvokeCpp(numberC);                int addResult = invoke.AddCpp(numberA, numberB);                int subResult = invoke.SubtractCpp(numberA, numberB);                int mutilResult = invoke.MultiplicationCpp(numberA, numberB);                int divResult = invoke.DividedCpp(numberA, numberB);                double powResult = invoke.PowerCpp(numberA, numberB);                double sqrtResult = invoke.SqrtCpp(numberA);                int getResult = invoke.GetIntCpp();                Console.WriteLine($"the {numberA} And {numberB} sum is:{addResult};sub is:{subResult};Mutil is:{mutilResult};div is:{divResult}; A^B is:{powResult}; root A is:{sqrtResult}; get value:{getResult}");            }            catch (Exception ex)            {                Console.WriteLine($"ex:{ex}");            }            Console.WriteLine("执行成功");            Console.ReadLine();        }    }}

右键点击 依赖项————添加项目引用————勾选 ClrDll————确定
在这里插入图片描述

运行 Debug
在这里插入图片描述

4. 总结

使用 CLR 作为 C# 调用 C++ 的桥梁C# 在依赖项中添加 CLR 项目后,可以直接调用 CLR 项目中的类及成员函数CLR 可以作为一个统一的对外接口,囊括所有 C++ 需要被外部调用的函数

点击全文阅读


本文链接:http://zhangshiyu.com/post/47646.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1