当前位置: 首页 > news >正文

C++调用C#方法(附踩坑点)

C++调用C#方法

  • 写在前面
    • 效果
    • 思路
    • 步骤
    • 可能的问题
  • 写在后面

写在前面

工作需要用C++调用C#写到代码,看来网上写的方法,自己也踩了一些坑,这里总结一下,我只试了CLR的方法。
主要参考了下面几篇博客
C++调用C#库简单例程(Lucky的outlook应该使用了这个技术
C++ 调用C#工程的 dll , 互相调用方法
C++调用C#的库

效果

这里用C++调用C#类的加法函数实现2+3,然后调用C#的Console.WriteLine打印
在这里插入图片描述

思路

C#生成DLL文件,C++调用C#的DLL

步骤

1、创建C# .NET Framework类库
注意是.NET Framework类库,不要创建错了
在这里插入图片描述
我命名为CSAdd
在这里插入图片描述
这里我们在CSAdd命名空间下写了一个Class1类。类中写两个函数,一个Add函数实现加法,一个Print函数调用Console.WriteLine
注意这个类在CSAdd命名空间下,所以后面的C++调用要先引用这个命名空间才能创建Class1类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace CSAdd
{public class Class1{public int Add(int a,int b){return a + b;}public void Print(String str){Console.WriteLine(str);}}
}

2、创建CPP项目
创建控制台应用
在这里插入图片描述
我命名为CPPInvokeCSAdd
在这里插入图片描述
在高级中开启clr
在这里插入图片描述
C/C++ —>语言---->符合模式设为否
在这里插入图片描述
我们写个main函数直接运行
在这里插入图片描述
可以看到exe文件确实生成在了\x64\Debug目录下
在这里插入图片描述

3、修改C#DLL的生成路径

在C#项目中把输出路径改为c++项目exe的输出路径上,也就是上面的\x64\Debug路径
在这里插入图片描述生成DLL,可以看到我们的CSAdd.dll生成在了这个目录下。
注意C#的DLL一定要和C++生成的exe在同一个目录下
在这里插入图片描述

4、编写C++程序,调用C#的DLL
关键点:
(1)使用#using 引用C#的dll,因为C#的dll放在C++项目下所以用../x64/Debug/CSAdd.dll代替完整路径F:\C++\CPPInvokeCSAdd\x64\Debug,写完整路径也可以。
(2)使用using namespace引入dll中的命名空间CSAdd,这样才能调用Class1
同时我们还迎入了C#的System命名空间,这是因为我们要在C++中创建C#的String对象(在System命名空间下)作为Print函数的参数(因为Print函数是C#实现了,所以不支持C++的std::string)。
(3)使用gcnew创建C#对象
(4)用 类名^ 表示C#的对象,所以这里用Class1^ dll,而不是Class1 dll。在C++/CLI中这个^类似于C++中的指针,但是因为C#有虚拟机,所以Class1^ dll实际是虚拟机在管内存的分配与回收,而不想C++的指针那样new的东西需要自己回收。
(5)因为dll->Print是调用C#中的方法,所以Print参数类型String也必须C#类型,所以创建了String^ resultStr
(6)为什么resultInt变量能调用ToString()方法?因为resultInt的类型是C#的int不是C++的int(我有点疑惑,具体得看看CLI的语法),所以直接dll->Print(resultInt.ToString())也是可以的。

//使用#using引用C# DLL,而不是#include;
#using "../x64/Debug/CSAdd.dll" 
// 引入CSAdd、System的命名空间
using namespace CSAdd;
using namespace System;int main()
{Class1^ dll = gcnew Class1();//使用gcnew创建dll中的对象指针int resultInt = dll->Add(2, 3);//调用dll对象中的方法String^ resultStr = gcnew String(resultInt.ToString());dll->Print(resultStr);return 0;
}

运行
在这里插入图片描述
5、如果之后要修改C#的代码
因为前面设置了C#项目中DLL是直接生成在C++项目的目录下的,所以修改完C#代码后直接在C#项目中点击生成就行了,不用该C++代码。
如果C++中#using "../x64/Debug/CSAdd.dll"这行编译器提示出错,把这行删了重写一次就好了。

可能的问题

报错:未能加载文件
在这里插入图片描述
可能原因:C++生成的exe和C#生成的dll不在同一个目录下,一定要在同一个目录下
在这里插入图片描述
解决办法:
C++项目的常规->输出目录、链接器->输出文件、c#的dll生成目录都是同一目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写在后面

初入职场,上班好累啊,呜呜呜。
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 初识redis:Set类型
  • element-ui下拉框的使用
  • 网络协议概述,ip协议,TCP协议,udp协议,二者区别,python中用socket类实现网络通信程序的编写(服务器套接字实现TCP编程,UDP编程)
  • GBase 8s数据库学习积累(2)
  • Android Audio
  • 餐厅点餐系统
  • python中在字符串前所加的字母r““、f““、b““、u““的含义
  • 2024年游泳耳机哪个牌子好?四大热门游泳耳机多维测评盘点!
  • kotlin adapter赋值失效
  • 【QT文件操作】---xml文件读取
  • Flat Ads:全球金融应用现状与发展趋势深度解析
  • [创业之路-138] :产品需求、产品研发、产品生产、库存管理、品控、售后全流程 - 时序图
  • linux下的oracle启动命令
  • 今年奥运会的场馆设计,竟然藏着这样的黑科技!
  • 反欺诈技术发展的现状与未来预测
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 08.Android之View事件问题
  • 2017 前端面试准备 - 收藏集 - 掘金
  • 230. Kth Smallest Element in a BST
  • Angular 响应式表单 基础例子
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript创建对象的四种方式
  • javascript面向对象之创建对象
  • Meteor的表单提交:Form
  • node-glob通配符
  • spring boot下thymeleaf全局静态变量配置
  • Theano - 导数
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue.js源码(2):初探List Rendering
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 笨办法学C 练习34:动态数组
  • 和 || 运算
  • 小程序button引导用户授权
  • 一些css基础学习笔记
  • 阿里云ACE认证学习知识点梳理
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • #100天计划# 2013年9月29日
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • $.ajax()参数及用法
  • (10)ATF MMU转换表
  • (160)时序收敛--->(10)时序收敛十
  • (3)选择元素——(17)练习(Exercises)
  • (Java数据结构)ArrayList
  • (六)软件测试分工
  • (数据结构)顺序表的定义
  • (一)十分简易快速 自己训练样本 opencv级联haar分类器 车牌识别
  • (转)setTimeout 和 setInterval 的区别
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • .chm格式文件如何阅读
  • .Net 8.0 新的变化
  • .net dataexcel 脚本公式 函数源码
  • .NET+WPF 桌面快速启动工具 GeekDesk
  • .Net的C#语言取月份数值对应的MonthName值