C#调用C++类,托管C++方式实现(创建C++ CLR dll项目)

news2024/11/20 0:41:12

        由于C#编写的是托管代码,编译生成微软中间语言,而C++代码则编译生成本地机器码(这种C++也有叫做本地C++或者非托管C++,VC6.0就是用于开发非托管C++代码的平台),这两种语言进行混合编程就存在一定困难。比较常用的方法是使用DllImport的方法,这种方法在网上有很多介绍,这里就不详细叙述了。但是用过这种方法的人都知道这种方法对于导出函数还可以但是却没法导出非托管C++类!非常的要命。

        然而,除了C#、非托管C++外,C系列中还存在一种语言叫做托管C++,这种语言语法上和非托管C++几乎一样,但是却和C#一样编译成为微软中间语言,这样托管C++就可以和C#良好地通信,即可以在C#中使用托管C++类。另外,托管C++还有两个及其重要的特性就是:可以调用非托管C++的类和函数!托管C++的程序集可以嵌套非托管C++编译的机器码!好强大的混合体。所以我们的技术路径也就明晰了:C#以托管C++为中介调用非托管C++的类和函数。换句话说也就是用托管C++给非托管C++代码做一个外壳包装供C#调用。

        换种方式解释:C#调用C++的dll库,如果调用C++的全局函数还好,估计可以直接调用,如果需要调用C++类里面的函数,因为C#和C++是两种不同的语言,两者之间不能直接调用,他们之间需要一个桥梁,而托管C++可以充当这个桥梁,这时需要创建一个C++ CLR dll,C#直接调用这个dll,间接调用原dll。

        下面讲解VS2017使用C#语言调用QT5.9.2 MSVC2017编译生成的dll的步骤。

第一步:准备普通的C++类库,这里使用QT5.9.2 MSVC2017生成的.h、.lib、.dll,64位。

这里不再详细叙述,dll导出的函数参数都是int、double等基本类型的。

第二步:VS2017创建C++ CLR项目,将普通C++dll重新封装。

一、创建C++ CLR空项目。

二、注意改为与原C++ dll相同的64位

三、原dll类库相关文件准备好,这里放在程序目录下library文件夹下

四、.h和lib引入项目,debug和release分别引入

选中项目名称,点击“项目》属性》VC++目录》包含目录”,设置.h所在文件夹

选中项目名称,点击“项目》属性》链接器》常规》附加库目录”,设置.lib所在文件夹

选中项目名称,点击“项目》属性》链接器》输入》附加库依赖项”,设置.lib名称

五、项目属性调整,调整为动态库dll项目:

选中项目名称,点击“项目》属性》常规》配置类型”,改为“动态库”

选中项目名称,点击“项目》属性》常规》公共语言运行时支持”,改为“公共语言运行时支持(/clr)”

“输出目录”、“目标文件名”等,根据需要进行修改。

选中项目名称,点击“项目》属性》C/C++》语言》符合模式”,确认为“否”

六、添加一个空的.h和一个.cpp文件,命名随意,这里命名为ManageCppDll.h,ManageCppDll.cpp。根据原dll的头文件编写这两个文件的内容。

.h文件内容

// ManageCppDll.h

#pragma once
#ifndef MANAGECPPDLL_H
#define MANAGECPPDLL_H

#include "sorter_filter.h"

/*
 * 请先初始化配置数据和计算数据,然后再调用计算函数进行计算
 */

public ref class ManageCppDll
{
public:
	ManageCppDll();
	~ManageCppDll();
	///
	/// \brief Init_SrcData:初始化导入计算数据,OVector格式
	/// \param data_count:in,数据数量
	/// \param x_coordinate:in,X轴坐标
	/// \param y_coordinate:in,Y轴坐标
	/// \param sensor_up:in,上传感器值
	/// \param sensor_down:in,下传感器值
	///
	void Init_SrcData(int data_count, double* x_coordinate, double* y_coordinate, double* sensor_up, double* sensor_down);//初始化导入计算数据
	///
	/// \brief Init_SrcData_3D:初始化导入3D计算数据,仅针对PCL点云移动最小二乘滤波,OVector<QVector>格式(Filter_PCL_MLS_3D函数)
	/// \param lineCount:in,行数量
	/// \param columnCountEveryLine:in,每行数据数量
	/// \param x_coordinate:in,X轴坐标
	/// \param y_coordinate:in,Y轴坐标
	/// \param sensor_up:in,上传感器值
	/// \param sensor_down:in,下传感器值
	///
	void Init_SrcData_3D(int lineCount, int* columnCountEveryLine, double* x_coordinate, double* y_coordinate, double* sensor_up, double* sensor_down);//初始化导入3D计算数据

	//递归中值平均滤波参数设置
	///
	/// \brief Init_Median_ConfigData:递归中值平均滤波参数设置
	/// \param layernum:滤波层数(一般设置为1)
	/// \param windownum:窗口长度
	/// \param masknum:掩码长度
	///
	void Init_Median_ConfigData(int layernum, int* windownum, int* masknum);//递归中值平均滤波参数设置
	///
	/// \brief Filter_Median:递归中值平均滤波,使用时先调用Init_SrcData导入待滤波数据,再调用Init_Median_ConfigData设置滤波窗口相关,最后调用此函数
	/// \param data_count:out,数据数量
	/// \param x_coordinate:out,X轴坐标
	/// \param y_coordinate:out,Y轴坐标
	/// \param sensor_up:out,上传感器值
	/// \param sensor_down:out,下传感器值
	/// \return
	///
	bool Filter_Median(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down);//递归中值平均滤波

	//calman滤波
	///
	/// \brief Init_Calman_ConfigData:calman滤波参数设置
	/// * 当我们更信任模型估计值时(模型估计基本没有误差),那么应该让Kg小一点,我们应该将R取大一点,Q取小一点
	/// * 当我们更信任观测值时(模型估计误差较大),那么应该让Kg大一点,我们应该将R取小一点,Q取大一点
	/// \param Q
	/// \param R
	///
	void Init_Calman_ConfigData(double Q, double R);//calman滤波参数设置
	///
	/// \brief Filter_Calman
	/// \param data_count:out,数据数量
	/// \param x_coordinate:out,X轴坐标
	/// \param y_coordinate:out,Y轴坐标
	/// \param sensor_up:out,上传感器值
	/// \param sensor_down:out,下传感器值
	/// \return
	///
	bool Filter_Calman(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down);//calman滤波

	//PCL-MLS(点云移动最小二乘滤波)相关
	///
	/// \brief Init_PCL_ConfigData:PCL移动最小二乘滤波参数设置
	/// \param MLSSearchRadius:最小二乘滤波半径
	///
	void Init_PCL_ConfigData(double MLSSearchRadius);//PCL滤波参数设置
	///
	/// \brief Filter_PCL_MLS
	/// \param data_count:out,数据数量
	/// \param x_coordinate:out,X轴坐标
	/// \param y_coordinate:out,Y轴坐标
	/// \param sensor_up:out,上传感器值
	/// \param sensor_down:out,下传感器值
	/// \return
	///
	int Filter_PCL_MLS(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down);//PCL移动最小二乘滤波;返回:0正常,<0异常
	///
	/// \brief Filter_PCL_MLS_3D
	/// \param lineCount:out,行数量
	/// \param columnCountEveryLine:out,每行数据数量
	/// \param x_coordinate:out,X轴坐标
	/// \param y_coordinate:out,Y轴坐标
	/// \param sensor_up:out,上传感器值
	/// \param sensor_down:out,下传感器值
	/// \return
	///
	int Filter_PCL_MLS_3D(int& lineCount, int* &columnCountEveryLine, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down);//PCL移动最小二乘滤波;返回:0正常,<0异常

private:
	// 类SORTER_CALCULATION的指针,用来调用类SORTER_CALCULATION的成员函数
	SORTER_FILTER* m_pImp;
};

#endif // MANAGECPPDLL_H

.cpp文件内容

// ManageCppDll.cpp

#include "ManageCppDll.h"
#include <vcclr.h>

	// 在构造函数中创建类CPerson的对象并在析构函数中将该对象销毁
	// 所有的成员函数实现都是通过指针m_pImp调用类CPerson的相应成员函数实现

ManageCppDll::ManageCppDll()
{
	m_pImp = new SORTER_FILTER();
}

ManageCppDll::~ManageCppDll()
{
	// 在析构函数中删除CPerson对象
	delete m_pImp;
}

//初始化导入计算数据
void ManageCppDll::Init_SrcData(int data_count, double* x_coordinate, double* y_coordinate, double* sensor_up, double* sensor_down)
{
	return m_pImp->Init_SrcData(data_count, x_coordinate, y_coordinate, sensor_up, sensor_down);
}
//初始化导入3D计算数据
void ManageCppDll::Init_SrcData_3D(int lineCount, int* columnCountEveryLine, double* x_coordinate, double* y_coordinate, double* sensor_up, double* sensor_down)
{
	return m_pImp->Init_SrcData_3D(lineCount, columnCountEveryLine, x_coordinate, y_coordinate, sensor_up, sensor_down);
}
//递归中值平均滤波参数设置
void ManageCppDll::Init_Median_ConfigData(int layernum, int* windownum, int* masknum)
{
	return m_pImp->Init_Median_ConfigData(layernum, windownum, masknum);
}
//递归中值平均滤波
bool ManageCppDll::Filter_Median(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down)
{
	return m_pImp->Filter_Median(data_count, x_coordinate, y_coordinate, sensor_up, sensor_down);
}
//calman滤波参数设置
void ManageCppDll::Init_Calman_ConfigData(double Q, double R)
{
	return m_pImp->Init_Calman_ConfigData(Q, R);
}
//calman滤波
bool ManageCppDll::Filter_Calman(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down)
{
	return m_pImp->Filter_Calman(data_count, x_coordinate, y_coordinate, sensor_up, sensor_down);
}
//PCL移动最小二乘滤波参数设置
void ManageCppDll::Init_PCL_ConfigData(double MLSSearchRadius)
{
	return m_pImp->Init_PCL_ConfigData(MLSSearchRadius);
}
//PCL移动最小二乘滤波
int ManageCppDll::Filter_PCL_MLS(int& data_count, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down)
{
	return m_pImp->Filter_PCL_MLS(data_count, x_coordinate, y_coordinate, sensor_up, sensor_down);
}
//PCL移动最小二乘滤波
int ManageCppDll::Filter_PCL_MLS_3D(int& lineCount, int* &columnCountEveryLine, double* &x_coordinate, double* &y_coordinate, double* &sensor_up, double* &sensor_down)
{
	return m_pImp->Filter_PCL_MLS_3D(lineCount, columnCountEveryLine, x_coordinate, y_coordinate, sensor_up, sensor_down);
}

最后编译生成dll。

第三步:在C#项目中调用,VS2017建立C#项目验证。

这里创建 Winform项目验证。注意原dll和CLR版的dll都要加入项目。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace cs_call_cpp_dll
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        unsafe private void button1_Click(object sender, EventArgs e)
        {
            ManageCppDll calculation_dll = new ManageCppDll();
            calculation_dll.Init_ConfigData(4, 10, 2, 0, 0);
            double[] array_x = { 0, 1, 2, 3, 4 };
            double[] array_y = { 0, 1, 2, 3, 4 };
            double[] array_up = { 2, 2, 2, 2, 2 };
            double[] array_down = { 0, 1, 6, 3, 4 };
            int coordinate_count = 5;
            fixed (double* coordinate_x = &array_x[0]
                , coordinate_y = &array_y[0]
                , coordinate_up = &array_up[0]
                , coordinate_down = &array_down[0])
            {
                calculation_dll.Init_CoordinateData(coordinate_count, coordinate_x, coordinate_y, coordinate_up, coordinate_down);
            }
            double thickness, thickness_center;
            calculation_dll.Calculation_THICKNESS(&thickness, &thickness_center);
            calculation_dll.Calculation_THICKNESS(&thickness, &thickness_center);
        }
    }
}

注意,如果用到了指针,需要加入unsafe,并设置“允许不安全代码”。double[]转为double*时用到了fixed,注意fixed的使用方法,这里不再多说。

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

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

相关文章

JWT的原理及实际使用

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 生活的理想&#xff0c;为了不断更新自己 ! 目录 1.JWT是什么&#xff1f; 2. jwt工具类介绍 3. jwt集成spa项目 1.JWT是什么&#…

MS5611的ZYNQ驱动试验之二 控制器功能考虑

上一篇BLOG简单介绍了MS5611的基本情况。这里我们考虑一下如何在ZYNQ里面实现&#xff0c;也就是规划PS和PL如何分工实现。 一般这种有一定简单时序的外设控制器我们可以采用两个方式编写&#xff1a; 1&#xff0c;用PL构造时序&#xff0c;做成所谓的加速器。 2&#xff0…

鲜花植物配送商城小程序的作用是什么

鲜花植物的市场需求非常高&#xff0c;尤其节假日或装饰/采购等需求更大&#xff0c;除了线下经销商外&#xff0c;还有鲜花植物供应商批发等&#xff0c;但其市场高需求的同时&#xff0c;经营痛点也比较明显。 通过【雨科】平台搭建鲜花植物商城&#xff0c;实现全产品线上展…

pg 字符相关操作

1. 字符串连接 1.1使用concat_ws&#xff08;a&#xff0c;b&#xff0c;c&#xff09; 语义&#xff1a;按a分隔bc 2.使用||连接 2.字符编码转换 3.获取字符串长度 4.大小写转换 5.替换

CentOS 7系统安装配置Zabbix 5.0LTS 步骤

目录 一、查看Zabbix官方教程&#xff08;重点&#xff09; 二、安装 Docker 创建 Mysql 容器 安装 Docker 依赖包 添加 Docker 官方仓库 安装 Docker 引擎 启动 Docker 服务并设置开机自启 验证 Docker 是否成功安装 拉取 MySQL 镜像 查看本地镜像 运行容器 停止和启…

Linux进程概念(二)--进程状态进程优先级

继上回书Linux进程概念&#xff08;一&#xff09;&#xff0c;我们初步了解了进程的一些相关概念以及如何创建和查看进程&#xff0c;对其原理和一些进程现象进行了分析和解释&#xff0c;那么今天&#xff0c;我们学习下一个进程知识-进程概念。 目录 1.操作系统的进程状态 …

vue3 新特性(defineOptions defineModel)

Vue3.3 新特性-defineOptions 背景说明&#xff1a; 有 <script setup> 之前&#xff0c;如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。 但是用了 <script setup> 后&#xff0c;就没法这么干了 setup 属性已经没有了&#xff0c;自然无法…

发布vue3组件到npm

目录 准备你的组件 创建项目 创建步骤 创建组件 封装我们要得组件 导出组件 打包 使用组件 发布包 创建npm账户 登录npm 切换npm源 发布到npm package.json package.json字段 确定版本号 版本号格式 版本号递增逻辑 vite 打包库模式 库模式配置 build配…

【数据结构】王道强化冲刺课

自用冲刺课复查 考点1 时间与空间复杂度 考点2 线性表 顺序表 链表 考点4567 栈和队列 矩阵 树 图 查找 排序

R实现动态条件相关模型与GARCH模型结合研究中美股市动态相关性(DCC-GARCH模型)

大家好&#xff0c;我是带我去滑雪&#xff01; 中美两国是全球最大的经济体&#xff0c;其经济活动对全球产业链和贸易体系都具有巨大影响。中美之间的经济互动包括大规模的贸易、投资和金融往来。这些互动不仅仅反映在经济数据上&#xff0c;还体现在股市上。中美股市的联动关…

使用任务定时执行软件的定时关机功能,控制电脑可用时间段

目录 定时关机功能可以设置有效的时间段 控制电脑可用时间段的意义 定时执行软件介绍 - 定时执行专家 定时关机设置方法 不可用时间段设置方法 注意事项 总结 在现代社会&#xff0c;电脑已经成为人们生活和工作中不可或缺的一部分。但是&#xff0c;长时间使用电脑也会对…

展会预告丨中国海洋装备博览会盛大开幕!箱讯科技亮相1T18展位

2023年10月12日-15日 中国海洋装备博览会暨2023世界航海装备大会 即将在福州海峡国际会展中心盛大开幕 箱讯科技携手上海虹口区工商联航运商会 亮相本次博览会 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 关于“中国海洋装备博览会” 中国海洋装…

DytanVO 代码复现(服务器端复现rtx3090)

源码地址 代码地址&#xff1a;https://github.com/castacks/DytanVO 环境配置 1.克隆github项目&#xff1a; git clone https://github.com/castacks/DytanVO.git2.利用yaml创建conda 环境&#xff1a; 修改yaml文件 name: dytanvo channels:- pytorch- conda-forge de…

PDM篇 | SOLIDWORKS 2024新功能

改进的视觉内容 优点 重要数据和系统信息一目了然。 • 通过装配体可视化功能&#xff0c;在 SOLIDWORKS 中以图形方式查看零部件数据&#xff0c;如工作流程状态。 • 使用特定图标迅速识别焊件切割清单零部件。 增强的数据保护和跟踪功能 优点 通过附加的审计跟踪信息&am…

Handler-ThreadLocal分析

ThreadLocal 源码分析 在 Android 的 Handler 机制下&#xff0c;ThreadLocal 提供了对不同线程本地变量的副本的保存&#xff0c;并且实现了线程数据的隔离&#xff0c;不同线程的数据不会产生错乱。且在一个线程结束后&#xff0c;其对应在 ThreadLocal 内的数据会被释放&am…

Win10 系统中用户环境变量和系统环境变量是什么作用和区别?

环境&#xff1a; Win10专业版 问题描述&#xff1a; Win10 系统中用户环境变量和系统环境变量是什么作用和区别&#xff1f; 解答&#xff1a; 在Windows 10系统中&#xff0c;用户环境变量和系统环境变量是两个不同的环境变量&#xff0c;它们具有不同的作用和区别 1.用…

数字化转型的环境中,MES管理系统的发展趋势如何

近年来&#xff0c;随着数字化技术的飞速发展&#xff0c;数字化转型以及成为企业发展的必然趋势。在这个过程中&#xff0c;制造业作为国民经济的重要支柱&#xff0c;也面临这前所未有的挑战和机遇。数字化转型下&#xff0c;制造业需要什么样的MES管理系统来应对这些挑战和机…

Domain_audit是一款基于渗透测试角度的域审计工具

关于Domain_audit 该工具是PowerView、Impacket、PowerUpSQL、BloodHound、Ldaprelayscan和Crackmapexec的包装器&#xff0c;用于自动执行枚举和在On-Prem Active Directory渗透测试期间执行的大量检查。 检查项目 Invoke-AD CheckAll将按顺序执行以下操作&#xff1a; 收…

竞赛选题 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

音视频开发岗位,2023年为何持续增加?如何应聘音视频岗位

随着基础设施的完善&#xff08;光纤入户、wifi覆盖、5G普及&#xff09;&#xff0c;加之2020年疫情的影响&#xff0c;将短视频、直播、视频会议、在线教育、在线医疗瞬间推到了顶峰&#xff0c;人们对音视频的需求和要求也越来越强烈。音视频开发是指利用计算机技术和相关编…