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

C# 调用 C++ 测试

0. 准备工作

  • 测试平台:Visual Studio 2019
  • 操作系统:Windows 10 专业版
  • CLR: Common Language Runtime
  • CLI: 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)
#endif


extern "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)
#endif


extern "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)
#endif

class 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++ 需要被外部调用的函数
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#调用 C++可以使用 C++/CLI(Managed C++)来实现。C++/CLI 是一种混合语言,可以同时使用 C++C#。通过创建一个 C++/CLI ,将 C++ 包装为公共成员,并在 C# 中直接调用方法。 以下是一个示例: ```cpp // C++ Class class MyCppClass { private: int value; public: MyCppClass(int v) : value(v) {} int GetValue() { return value; } }; ``` ```cpp // C++/CLI Wrapper #pragma managed #include "MyCppClass.h" public ref class MyCppWrapper { private: MyCppClass* cppClass; public: MyCppWrapper(int v) { cppClass = new MyCppClass(v); } ~MyCppWrapper() { delete cppClass; } int GetValue() { return cppClass->GetValue(); } }; ``` ```c# // C# 使用 C++/CLI Wrapper class Program { static void Main(string[] args) { MyCppWrapper wrapper = new MyCppWrapper(42); int value = wrapper.GetValue(); Console.WriteLine(value); // 输出 42 } } ``` 在这个示例中,我们创建了一个 C++ `MyCppClass`,并使用 C++/CLI 创建了一个包装器 `MyCppWrapper`。在 `MyCppWrapper` 中,我们实例化了 `MyCppClass` 的对象,并将其封装在公共成员方法中,以供 C# 调用。 请注意,C++/CLI 项目需要将 `Common Language Runtime Support` 设置为 `/clr`。另外,如果 C++ 有其他依赖项,需要在 C++/CLI 项目中引用这些依赖项。 使用 C++/CLI 可以方便地在 C#调用 C++方法,但需要注意确保 C++ 的可访问性和正确的函数签名,以便在 C# 中正确使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值