上一篇文章最后,提出的一个问题:如果一个c++库中有很多方法,需要一个个声明??这样岂不是要写很多代码??,而且没有智能提示看到提供了那些方法。

如下图:

如果有朋友需要用这种方式调用,而又不知道怎么使用,请看我的上一篇文章:https://www.cnblogs.com/skyfreedom/p/11773597.html

针对上述问题,在使用过程中总结,记录下来,供需要的朋友参考。

重点:通过CLI实现c#调用c++

看完了本文,相信你就会了,一步步操作就是了。

一、 新建一个netcore控制台应用程序;

这个是我们测试调用C++用的

二、 创建一个c++空项目

如图:

项目创建完成,我们添加一个类,写几个方法,这儿就简单写一个计算器的加减乘除吧!

在CaculateData.h中添加如下代码,定义几个函数声明;

#include <stdio.h>
#include <stdlib.h>
#include <iostream> #ifdef CaculateDLL_EXPORTS
#define Calculate_EXPORTS __declspec(dllexport)
#else
#define Calculate_EXPORTS __declspec(dllimport)
#endif extern "C" Calculate_EXPORTS int Add(int numberA, int numberB); extern "C" Calculate_EXPORTS int Subtract(int numberA, int numberB); extern "C" Calculate_EXPORTS int Multiplication(int numberA, int numberB); extern "C" Calculate_EXPORTS int Divided(int numberA, int numberB); class CaculateData
{
public:
CaculateData();
~CaculateData(); };

可以看到,#ifdef的宏没有定义,所以我们需要添加一个宏:

项目右键---属性---配置属性---C/C++---预处理器---预处理器定义,将定义的宏添加进去;

可以看到,定义好了,颜色就变成紫色的,说明已经声明了宏;

在CaculateData.cpp中实现这几个方法;

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

修改C++工程项目输出目录,这儿主要是便于CLI引用,我们这儿同意定义到Testinvoking项目的输出目录..\bin\Debug\netcoreapp2.2

(修改步骤:项目右键—属性—配置属性—常规—输出目录)

配置类型修改为:动态库.dll

(修改步骤:项目右键—属性—配置属性—常规—配置类型)

然后生成;

结果如下:可以看到,日志已经打印出来,告知我们生成成功了。

去对应目录看一下,也OK

三、新建一个CLR项目

这个项目就是来实现C#调用C++的

因为需要调用Caculate.dll,所以需要引用它;

配置属性—VC++目录—库目录(把刚刚生成Caculate.dll的路径添加进去)

同时引用库:

添加一个类InvokeCon.cpp,用它来调用Caculate.dll中的方法

InvokeCon.cpp代码如下:

#include "InvokeCon.h"

InvokeCon::InvokeCon()
{
} int InvokeCon::AddCli(int numberA, int numberB)
{
return Add(numberA, numberB);
} int InvokeCon::SubtractCli(int numberA, int numberB)
{
return Subtract(numberA, numberB);
} int InvokeCon::MultiplicationCli(int numberA, int numberB)
{
return Multiplication(numberA, numberB);
} int InvokeCon::DividedCli(int numberA, int numberB)
{
return Divided(numberA, numberB);
}

InvokeCon.h代码:

#pragma once

#include <iostream>
#include "C:\Users\tjy\source\repos\TestInvoking\Caculate\CaculateData.h"//引用库声明对应文件路径
public ref class InvokeCon
{
public:
InvokeCon(); int AddCli(int numberA, int numberB);
int SubtractCli(int numberA, int numberB);
int MultiplicationCli(int numberA, int numberB);
int DividedCli(int numberA, int numberB);
};

然后编译,修改编译类型为动态库dll

然后生成:此时就产生了CliDll.dll库

四、c#通过引用CliDll.dll来调用Caculate中的方法

1、添加对Dll的引用;

2、在C#项目中添加测试代码:

可以看到,此时就能够调用多个方法,而且会有方法名提示!

using System;

namespace TestInvoking
{
public 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()); InvokeCon invoke = new InvokeCon();
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();
}
}
}

OK,完成!

代码已经放到了github,需要的朋友可以去看,就是这篇文章简单的demo:

github地址:https://github.com/tomorrowGooddays/Invoke

说明:操作过程中有任何问题可以留言讨论,写错不易,欢迎纠正!原创文章,转载请说明出处,谢谢!

C#如何调用C++(进阶篇)的更多相关文章

  1. C#如何调用C++(基础篇)

    闲暇之余,记一下笔记!记录一下c#如何调用C++的动态库(dll). 步骤: 一.创建一个C++类,例如: AddOperate.h extern _declspec(dllexport) int S ...

  2. Membership三步曲之进阶篇 - 深入剖析Provider Model

    Membership 三步曲之进阶篇 - 深入剖析Provider Model 本文的目标是让每一个人都知道Provider Model 是什么,并且能灵活的在自己的项目中使用它. Membershi ...

  3. python 面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  4. 最快让你上手ReactiveCocoa之进阶篇

    前言 由于时间的问题,暂且只更新这么多了,后续还会持续更新本文<最快让你上手ReactiveCocoa之进阶篇>,目前只是简短的介绍了些RAC核心的一些方法,后续还需要加上MVVM+Rea ...

  5. ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL

    http://www.cnblogs.com/John-Connor/archive/2012/05/03/2478821.html 引言-- 在初级篇中,我们介绍了如何利用基于ASP.NET MVC ...

  6. Python之路【第十七篇】:Django【进阶篇 】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  7. PHP学习笔记 - 进阶篇(11)

    PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...

  8. PHP学习笔记 - 进阶篇(10)

    PHP学习笔记 - 进阶篇(10) 异常处理 抛出一个异常 从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被 ...

  9. PHP学习笔记 - 进阶篇(9)

    PHP学习笔记 - 进阶篇(9) 图形图像操作 GD库简介 GD指的是Graphic Device,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新 ...

随机推荐

  1. openwrt环境中某个运行在host端的软件如何安装到openwrt的$(STAGING_DIR_HOST)/bin下

    可参考示例:见'git grep host-build.mk package/{system,utils}'

  2. js求数组最大值方法

    定义数组 var arr = [-1, 1, 101, -52, 10, 1001, 1001] 1.es6拓展运算符... Math.max(...arr) 2.es5 apply(与方法1原理相同 ...

  3. 发布一个史上最简单代码最少Javascript Timer,解决一切定时执行的问题

    这个函数实现如下 function TimerStart(func,delay) { var TimerID = window.setInterval( function() { if(!func() ...

  4. word 2010中设置默认粘贴为 只保留文本粘贴【visio也适用于快捷键方式】

    VISIO也适用如下方式: 3. 当然也可以直接是 Ctrl + Alt + V打开选择性粘贴选项卡 来选择其中某项来粘贴也是可以的 转: word 2010中设置默认粘贴为 只保留文本粘贴 2012 ...

  5. Python 函数返回值、作用域

    函数返回值 多条return语句: def guess(x): if x > 3: return "> 3" else: return "<= 3&qu ...

  6. iOS-app清除缓存

    一直寻寻觅觅找app的清除缓存的方法,发现:并没有什么固定的方法,你既然有做对应的缓存机制,这个机制就应该有清除缓存的方法.例如如果你使用某个第三方的图片库,这个库有缓存机制,那么它就应该提供对应的清 ...

  7. Redis源码解析

    一.src/server.c 中的redisCommandTable列出的所有redis支持的命令,其中字符串命令包括从get到mget:列表命令从rpush到rpoplpush:集合命令包括从sad ...

  8. 《C语言程序设计教程》学习笔记

    <C语言程序设计教程>--朱鸣华.刘旭麟等 第一章 C语言概述 1.C语言的特点: 1)兼具高级.低级语言的双重能力(C语言允许直接访问物理地址,能够进行位操作,能实现汇编语言的大部分功能 ...

  9. Ext.jsTree 向子节点添加叶子节点

    // 定义搜索节点树结构Store const nodeStore = Ext.create('Ext.data.TreeStore', { autoLoad : true, id : 'nodeSt ...

  10. 【C/C++开发】ffplay中的FrameQueue的自我理解

    最近在研究ffplay,以下是本人今天在研究FrameQueue的时候整理的笔记,如有错误还请有心人指出来~ //这个队列是一个循环队列,windex是指其中的首元素,rindex是指其中的尾部元素. ...