基于C++/CLI实现C#与C++互调过程中的注意事项

news2024/12/26 11:21:57

目录

  • 一、基于C++/CLI 的调用原理
  • 二、注意事项
    • 如何基于VS2010完成C#调用C++开发过程
      • 1、生成C++应用程序(非托管代码)
      • 2、基于C++/CLI生成托管代码
      • 3、C#调用
    • 如何基于VS2010完成C++调用C#开发过程
  • 三、C++/CLI与COM组件对比

一、基于C++/CLI 的调用原理

C++/CLI (Common Language Infrastructure)是一种特殊的 C++ 语言,它支持在 .NET 平台上进行开发和编译。C++/CLI 可以让开发人员使用 C++ 语言来编写 .NET 应用程序,并且可以直接访问和使用 .NET 框架中的类库。其支持托管代码和非托管代码:C++/CLI 中既可以编写非托管代码,也可以编写托管代码。这使得开发人员可以利用现有的 C++ 代码库,并将其集成到 .NET 应用程序中。

托管代码是指运行在 .NET 运行时(Common Language Runtime)中的代码。托管代码是由编译器生成的,它们包含了一些元数据信息,这些信息可以被 .NET 运行时用来管理代码的执行、内存分配、垃圾回收等操作。

非托管代码是指不运行在 .NET 运行时中的代码。这些代码通常是使用 C 或 C++ 等语言编写的,并且直接访问计算机的硬件资源和操作系统 API。非托管代码不包含元数据信息,也不依赖于 .NET 运行时,因此它们无法直接与托管代码进行交互。(即待调用的C++ 应用程序)

因此我们的思路为:
1、C#调用C++:通过C++/CLI 的委托代码调用C++应用程序(非委托代码),从而生成.NET应用,实现基于C#的访问。
其中,每个环节都是利用动态链接库(.dll)交互实现。
2、C++调用C#:C++基于所支持的clr,通过调用C#生成的dll作为其引用,实现访问C#命名空间域下的功能。

二、注意事项

如何基于VS2010完成C#调用C++开发过程

1、生成C++应用程序(非托管代码)

这个就是我们需要被调用的应用程序,根据各个项目需求自行设计。需要注意,编译生成的文件需改成.dll格式而非传统的.exe控制台,如下所示:
在这里插入图片描述

2、基于C++/CLI生成托管代码

这一步摸索了一段时间,感觉和编译器的版本也有关系,VS2010确实有点老了,存在不便。因此,本人详细罗列了相关操作流程。

首先,我们需要新建一个CLR(Common Language Runtime)环境。这里说明下:C++/CLI 和CLR关系,前者是针对 .NET 平台而设计的一种编程语言,可以方便地将 C++ 代码与 .NET 技术集成在一起,而后者则是 .NET 平台的核心组件,提供了运行时环境和基础设施。

选中**”类库“**!!!同时注意所使用的.NET FrameWork版本。
(可能是本人操作问题,之前尝试选中的是”CLR空项目“,结果出现C#无法访问其空间域。)
在这里插入图片描述

完成后,为项目添加C++应用程序编译生成的dll引用
在这里插入图片描述

再将C++应用程序代码作为现有项添加至”源文件“,并将其路径添加至包含目录。
在这里插入图片描述
顺道给个代码实现demo:

// myCLR.h

#pragma once
#include "myTest.h"//C++应用程序 头文件
#include "string.h"
#include <msclr/marshal_cppstd.h>

using namespace System;
using namespace msclr::interop;

namespace myCLR {
	//ref class 作为委托类,从而使得C#可对Person_CLI进行访问
	public ref class Person_CLI
	{
	public:
		void initPersonClass();
		void setPersonInfo(System::String^ name,int age,double height);
	private:
		Person *_p;//C++应用程序 声明Person类对象
		string convertToStd(System::String^ str);
	};
}

// 这是主 DLL 文件。

#include "stdafx.h"
#include "myCLR.h"


void myCLR::Person_CLI::initPersonClass(){
    //new 
	_p=new Person();
}
void myCLR::Person_CLI::setPersonInfo(System::String^ name,int age,double height){
	//访问类的成员函数
	string strName=convertToStd(name);
	_p->init(strName,age,height);
	_p->showInfo();
}

//System::String^ str 转为 string
//因为C#只有System::String^类型, 与C++应用程序函数的参数类型string  不兼容
string myCLR::Person_CLI::convertToStd(System::String^ str){
	marshal_context context;
    return context.marshal_as<std::string>(str);
}

3、C#调用

将添加C++/CLI生成的DLL,即可访问
在这里插入图片描述

using System;
using System.Runtime.InteropServices;
using myCLR;//添加命名空间域

class Program
{ 
    static void Main(string[] args)
    {
        //直接访问
        Person_CLI _cl = new Person_CLI();
        _cl.initPersonClass();
        _cl.setPersonInfo("Tom",10, 30.2);
        Console.ReadKey();
    }
}


正常输出结果
在这里插入图片描述

如何基于VS2010完成C++调用C#开发过程

1、在C++应用程序的属性中设置:公共语言运行时支持(/clr);
在这里插入图片描述

2、将C#生成的dll作为引用添加至C++应用程序;

首先,需要基于待调用的C#类库编译生成dll。 此外给个C#代码的Demo:

//CsharpDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsharpDemo
{
    public class Class1
    {
        public void showInfo(){
            Console.WriteLine("showInfo()执行成功");
        }
    }
}

然后,再将dll作为引用添加至C++应用程序。
C++解决方案属性配置-添加引用

3、文件中添加C#的命名空间域

//cppDemo.cpp
#include "stdafx.h"
#include <iostream>

using namespace std;
using namespace CsharpDemo;//添加C#的命名空间域

int _tmain(int argc, _TCHAR* argv[])
{
	//新建C#中的对象  clr中用“^”代替指针“*”,用“gcnew”代替“new”
	//由于C#类会自动释放内存,因此不需要像C++手动delete释放
	Class1 ^ _cl=gcnew Class1();
	//调用C#类的方法
	_cl->showInfo();

	system("pause");
	return 0;
}

运行结果

三、C++/CLI与COM组件对比

C++ ATL(Active Template Library)并不能像 C++/CLI 一样实现混合使用托管和非托管代码。C++ ATL 是一种基于 COM 技术的 C++ 库,主要用于编写 COM 组件和应用程序。它不是一种语言,而是一种库,提供了一些在编写 COM 组件时经常使用的类和函数。

假如已经有一个现有的 C++ 应用程序,并且想要让 C# 调用它,那么使用 C++ ATL 可能不是最好的选择,因为这需要将现有的 C++ 应用程序重写为 COM 组件,并在 C# 中使用 COM Interop 来访问该组件,这可能会带来一些复杂性和性能开销。

相比之下,使用 C++/CLI 则更加方便和直接。通过编写 C++/CLI 包装器,可以直接将现有的 C++ 应用程序集成到 .NET 应用程序中,并且可以充分利用 .NET 平台所提供的各种优势,如自动内存管理、强类型等。同时,C++/CLI 还支持混合使用托管和非托管代码,因此可以轻松地实现与操作系统 API、硬件驱动程序、第三方库等非托管系统的交互。

不过在一些情况下,使用 ATL 可能会比使用 C++/CLI 更加高效和灵活。这是因为 ATL 提供了许多内置的 COM 基础类和模板,使得开发者可以快速创建高效的 COM 组件。此外,ATL 还提供了一套可选的 Active Template Library 对象模型(ATL OLE DB),这个对象模型提供了对 OLE DB 数据库访问的支持,使得开发者可以更方便地实现数据库相关的功能。

基于COM组件的相关操作可以回顾:
基于COM组件实现C#调用C++类对象过程中的注意事项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构---队列的实现

文章目录 前言一、什么是队列&#xff1f;二、队列接口的实现 1.队列结构的定义2.接口实现总结 前言 队列是一种特殊的线性表。 特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&a…

【Vue.js】1668- 初中级前端必须掌握的 10 个 Vue 优化技巧

优化 Vue.js 应用性能是每个前端开发人员都需要关注的问题。本文我将分享 10 个初中级前端必须掌握的 Vue.js 优化技巧&#xff0c;无论您是正在学习 Vue.js&#xff0c;还是已经在应用开发中使用它&#xff0c;希望这些技巧都会对你的工作有所帮助。 1. 优雅的设置 v-for 中的…

Java 中常见的 Exception 有哪些

Java 是一种广泛使用的编程语言&#xff0c;它的强大和流行程度在很大程度上归功于它的异常处理机制。异常是在程序执行期间出现的错误或意外情况。在 Java 中&#xff0c;异常是通过抛出和捕获异常对象来处理的。在本文中&#xff0c;我们将介绍 Java 中的一些常见异常类型及其…

浅堆深堆解读

浅堆&#xff08;Shallow Heap&#xff09; 浅堆是指一个对象所消耗的内存。在32位系统中&#xff0c;一个对象引用会占据4个字节&#xff0c;一个int类型会占据4个字节&#xff0c;long型变量会占据8个字节&#xff0c;每个对象头需要占用8个字节。根据堆快照格式不同&#x…

【STM32】知识补充 深入探讨预分频器

【STM32】知识补充 深入探讨预分频器 概述分频器是什么工作原理计数器预分频器触发器预分频器模数计数器预分频器上升沿和下降沿 应用场景微控制器时钟预分频通信系统中的频率合成计时器与 PWM 波形生成数字电路设计中的同步与计时 预分频器实现方法硬件预分频器软件预分频器 案…

Swift之深入解析如何使用和自定义高级运算符

一、前言 在我之前的博客 Swift之深入解析如何自定义操作符 介绍了“基本运算符”&#xff0c;Swift 还提供了数种可以对数值进行复杂运算的高级运算符&#xff0c;它们包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。与 C 语言中的算术运算符不同&…

【flask】理解flask的几个难点,难啃的骨头,线程隔离啥的

1.三种路由和各自的比较 2.配置文件所有的字母必须大写 3.if __name__的作用 4.核心对象循环引用的几种解决方式–难 5.Flask的经典错误 6.上下文管理器 7.flask的多线程和线程隔离 三种路由 方法1&#xff1a;装饰器 python C#, java 都可以用这种方式 from flask import F…

SSM整合(三) | 异常处理器 - 项目异常的处理方案

文章目录 异常处理器异常处理器快速入门项目异常处理 异常处理器 异常处理器快速入门 程序开发过程中不可避免的会遇到异常现象 出现异常现象的常见位置与常见原因如下&#xff1a; 框架内部抛出的异常&#xff1a;因使用不规范导致 数据层抛出的异常&#xff1a;因外部服务器…

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据&#xff0c;你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块&#xff0c;它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中&#xff0c;我们将介绍 statsmodel 库的基础知识、如何…

【技巧】Excel序号设置自动更新

做Excel表格的时候&#xff0c;我们经常需要设置序号&#xff0c;在输入序号的时候&#xff0c;你是不是这样做&#xff1f;手动输入序号1&#xff0c;再向下填充&#xff0c;当遇到有不想要的内容&#xff0c;点删除后&#xff0c;发现中间的序号就不连贯了&#xff0c;再手动…

二十五、OSPF高级技术——开销值、虚链路、邻居建立、LSA、多进程

文章目录 调试指令&#xff08;三张表&#xff09;1、邻居表&#xff1a;dis ospf peer brief2、拓扑表&#xff08;链路状态数据库&#xff09;&#xff1a;dis ospf lsdb3、路由表&#xff1a;dis ip routing-table 一、OSPF 开销值/度量值&#xff08;cost&#xff09;1、co…

代码审计笔记之开篇

思想 代码审计是从软件测试发展而来&#xff0c;早起一般采用常规软件测试与渗透测试的手段来发现源码漏洞&#xff0c;但是随着软件规模的越来越大&#xff0c;架构越来越复杂&#xff0c;安全漏洞和后门也越来越多越来越隐蔽&#xff0c;这使得传统的软件测试方法很难检出源…

【Java入门合集】第二章Java语言基础(一)

【Java入门合集】第二章Java语言基础&#xff08;一&#xff09; 博主&#xff1a;命运之光 专栏JAVA入门 学习目标 掌握变量、常量、表达式的概念&#xff0c;数据类型及变量的定义方法&#xff1b; 掌握常用运算符的使用&#xff1b; 掌握程序的顺序结构、选择结构和循环结构…

C/C++每日一练(20230501)

目录 1. 对链表进行插入排序 &#x1f31f;&#x1f31f; 2. 找出小于平均值的数 ※ 3. 二叉树的最大深度 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 对链表进行…

【五一创作】Apollo(入门)

Apollo(入门) Quick Start 配置中心是一种统一管理各种应用配置的基础服务组件 Apollo&#xff08;阿波罗&#xff09;是携程框架部门研发的分布式配置中心&#xff0c;能够集中化管理应用不同环境、不同集群的配置&#xff0c;配置修改后能够实时推送到应用端&#xff0c;并且…

Springboot 实战一个依赖解决XSS攻击

1. 什么是XSS介绍 XSS: Cross Site Scripting&#xff0c;为不和层叠样式表(Cascading Style Sheets, CSS) 的缩写混淆&#xff0c;故将跨站脚本攻击缩写为XSS。 恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中 Web里面的Scrip…

【高并发】并发数据结构与多核编程

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于多处理器编程的艺术进行的&#xff0c;每个知识点的修正和深入主要…

【JavaEE初阶】认识线程(Thread)

目录 &#x1f33e; 前言 &#x1f33e; 了解线程 &#x1f308;1.1 线程是什么&#xff1f; &#x1f308;1.2 一些基本问题 &#x1f33e;2、创建线程的方式 &#x1f308; 2.1 继承Thread类 &#x1f308; 2.2 实现Runnable接口并重写run()方法 &#x1f308; 注意…

有哪些好的学习方法?学霸们自己在用,却不愿意透露的

临近期末,很多家长都在跟我咨询,怎么才能提升孩子的学习效率? 原因就是,每天看着自己的孩子学习到深夜,但不少内容还是记不住, 学习和复习的效果非常的不理想。 今天,给大家分享的方法,是我自己一直也都在用的方法,效果非常的棒。 学长Ron,江苏某省重点高中毕业,高…

给公司搭建一个人才库系统,前台(信息填写+简历上传)后台(筛选功能+下载简历)

首先指出目前代码的不足之处&#xff1a; 如果公司使用&#xff0c;代码还存在风险问题&#xff0c;需要增加防火墙、防PHP攻击、后台加验证等操作 以下指南&#xff1a; 1.Mod Security 和 Fail2Ban 是开源的安全软件&#xff0c;您可以在宝塔面板上安装和配置这些软件来增强您…