因为业务需要学习C#调用C++的库
但是C# 是在托管机制的运行
C++ 在非托管机制下运行
托管 是主机自己回收内存,统一释放。
非托管 自己使用内存自己释放。
环境 VS2017
大致实现思路:首先创建C++项目 实现非托管动态库 ,其次在创建C++项目加载非托管运行库,发布成托管运行库,然后C#引用dll库。
具体实现:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qt8DoVs0-1648113160602)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\创建C#空项目.png)]
1.首先在该工程的解决方案上右键->添加->新建项目->Visual C++ -> Windows 通用 -> 空白应用 ,在下面名称地方输入 ExportDll 并选择位置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SLBMeDcZ-1648113160604)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\创建非托管C++空项目.png)]
2.接下来创建类,在ExportDll项目上右键->添加->新建项->c++类 ,输入类名及位置,添加进入下一步,添加类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5uxOHAD-1648113160605)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\非托管类1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3NaTmrU5-1648113160605)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\非托管类2.png)]
ExportDllApi.h
//重要代码
#ifdef EXPORTDLL_EXPORTS
#define EXPORTDLL_CLASS __declspec(dllexport)
#else
#define EXPORTDLL_CLASS __declspec(dllimport)
#endif
extern "C" EXPORTDLL_CLASS int Add(int numberA, int numberB);
extern "C" EXPORTDLL_CLASS int Subtract(int numberA, int numberB);
extern "C" EXPORTDLL_CLASS int Multiplication(int numberA, int numberB);
extern "C" EXPORTDLL_CLASS int Divided(int numberA, int numberB);
ExportDllApi.cpp
#include "ExportDllAPI.h"
EXPORTDLL_CLASS int Add(int numberA, int numberB)
{
return numberA + numberB;
}
EXPORTDLL_CLASS int Subtract(int numberA, int numberB)
{
return numberA - numberB;
}
EXPORTDLL_CLASS int Multiplication(int numberA, int numberB)
{
return numberA * numberB;
}
EXPORTDLL_CLASS int Divided(int numberA, int numberB)
{
if (numberB == 0) {
std::cout << "除数不能为空" << std::endl;
}
return numberA / numberB;
3.接下来是对该项目的配置, ExportDll项目上右键->属性 进行配置。
在常规属性中配置 输出目录(一般放置在C#项目Debug目录下,后期因为C#程序要加载,尽可能程序库都放置在C#加载的目录下) 和配置类型(配置成动态库)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tN6hKzgz-1648113160606)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportDll属性配置1.png)]
还要配置C/C++中的预处理 加入宏EXPORTDLL_EXPORTS
;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LVg4crjJ-1648113160607)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportDll属性配置2.png)]
注意:平台选择Win32
然后在ExportDll项目上右键->生成(或者 重新生成) ,在前面配置的输出目标(C#程序Debug目录下)会生成ExportDll.dll文件。
1.首先在该工程的解决方案上右键->添加->新建项目->Visual C++ -> Windows 通用 -> 空白应用 ,在下面名称地方输入 ExportCLI 并选择位置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cf7uEX8C-1648113160607)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\创建托管C++空项目.png)]
2.接下来创建类,在ExportCLI项目上右键->添加->新建项->c++类 ,输入类名及位置,添加进入下一步,添加类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDBCFzOF-1648113160608)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\托管1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ijn35kYD-1648113160608)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\托管2.png)]
ExportCLI.h
#pragma once
#include
#include "E:\Toshiba\code\TestIPC\CShap\CsharpDemo1\ExportDll\ExportDllAPI.h"
public ref class ExportCLI
{
public:
ExportCLI();
int AddCli(int numberA, int numberB);
int SubtractCli(int numberA, int numberB);
int MultiplicationCli(int numberA, int numberB);
int DividedCli(int numberA, int numberB);
};
ExportCLI.cpp
#include "ExportCLI.h"
ExportCLI::ExportCLI()
{
}
int ExportCLI::AddCli(int numberA, int numberB)
{
return Add(numberA, numberB);
}
int ExportCLI::SubtractCli(int numberA, int numberB)
{
return Subtract(numberA, numberB);
}
int ExportCLI::MultiplicationCli(int numberA, int numberB)
{
return Multiplication(numberA, numberB);
}
int ExportCLI::DividedCli(int numberA, int numberB)
{
return Divided(numberA, numberB);
}
3.接下来是对该项目的配置, ExportCLI项目上右键->属性 进行配置。
在常规属性中配置 配置类型(配置成动态库)和公共语言运行时支持(选择公共语言运行时支持(/cli) )
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pa05EQs8-1648113160609)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportCLI属性配置1.png)]
在 VC++目录 -> 库目录 (一般放置在C#项目Debug目录下,后期因为C#程序要加载,尽可能程序库都放置在C#加载的目录下)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1Zr7d9s-1648113160610)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportCLI属性配置4.png)]
在C/C++ ->语言 中符合模式选“否”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFiZ6w1e-1648113160611)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportCLI属性配置2.png)]
在连接器->输入 附加依赖项加入 ExportDll.lib (上一个C++非托管项目,生成的库问题件)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mk03Li4k-1648113160612)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\ExportCLI属性配置3.png)]
注意:平台选择Win32
然后在ExportCLI项目上右键->生成(或者 重新生成) ,会生成ExportCLI.dll文件。
1.首先进行配置,在项目CsharpDemo项目下面的引用,引用ExportCLI库。
在项目下引用,右键->添加引用->项目 选择ExportCLI
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSWDaD4H-1648113160612)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\引用添加.png)]
2.在项目CsharpDemo上右键->属性->生成 (平台目标x86)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OKsIN93Y-1648113160613)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\生成平台选择.png)]
3.写入代码
program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CsharpDemo1
{
class Program
{
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());
ExportCLI invoke = new ExportCLI();
int addResult = invoke.AddCli(numberA, numberB);
int subResult = invoke.SubtractCli(numberA, numberB);
int mutilResult = invoke.MultiplicationCli(numberA, numberB);
int divResult = invoke.DividedCli(numberA, numberB);
Console.WriteLine($"the {numberA} And {numberB} sum is:{addResult};sub is:{subResult};Mutil is:{mutilResult};div is:{divResult}");
}
catch (Exception ex)
{
Console.WriteLine($"ex:{ex}");
}
Console.WriteLine("执行成功");
Console.ReadLine();
}
}
}
运行成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfF96qja-1648113160614)(E:\Toshiba\code\TestIPC\csharp-call-cgaga-dll\img\成功.png)]
切记 一定要把CsharpDemo 设置为启动项
源码下载