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

这篇具有很好参考价值的文章主要介绍了C#调用C++类,托管C++方式实现(创建C++ CLR dll项目)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        由于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#调用C++类,托管C++方式实现(创建C++ CLR dll项目),c#,c++,开发语言二、注意改为与原C++ dll相同的64位

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

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

C#调用C++类,托管C++方式实现(创建C++ CLR dll项目),c#,c++,开发语言C#调用C++类,托管C++方式实现(创建C++ CLR dll项目),c#,c++,开发语言四、.h和lib引入项目,debug和release分别引入

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

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

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

C#调用C++类,托管C++方式实现(创建C++ CLR dll项目),c#,c++,开发语言选中项目名称,点击“项目》属性》链接器》输入》附加库依赖项”,设置.lib名称

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

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

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

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

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

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

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

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

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

.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的使用方法,这里不再多说。

C#调用C++类,托管C++方式实现(创建C++ CLR dll项目),c#,c++,开发语言文章来源地址https://www.toymoban.com/news/detail-725698.html

到了这里,关于C#调用C++类,托管C++方式实现(创建C++ CLR dll项目)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity——在C#中调用C++动态链接库(DLL)

    1、新建C++空项目 打开VS,新建一个C++空项目,自命名项目名称与位置。 2、配置项目属性为动态链接库 右键项目,点击属性,打开项目属性页,将常规中的配置类型改为动态库(.dll)。  3、添加.h头文件 右键头文件,点击添加—新建项,选择头文件.h,命名为DllForUnity.h,点击

    2024年02月10日
    浏览(43)
  • C#调用C++封装的SDK库(dll动态库)——下

    一、说明 上一篇我们相当于封装的是C语言风格的动态dll库,供C#来调用的。 C#调用C++封装的SDK库(dll动态库)——上 如果我们要封装的是下面的类呢?我们该怎么办?大家先思考下。  二、思路 不知道大家还记得设计模式中的单例模式吗? 我们可以采用类似的处理方式,通过

    2023年04月25日
    浏览(41)
  • C#(.Net) 将非托管dll嵌入exe中

    前往我的主页以获得更好的阅读体验 C#(.Net) 将非托管dll嵌入exe中 - DearXuan的主页 https://blog.dearxuan.com/2021/12/26/C-Net-%E5%B0%86%E9%9D%9E%E6%89%98%E7%AE%A1dll%E5%B5%8C%E5%85%A5exe%E4%B8%AD/ 托管dll实际上是指C#编写的dll,可以直接右键“引用”导入 而大部分情况下,我们需要引用C++写的dll,如果你

    2024年02月08日
    浏览(45)
  • Visual Studio关于C#项目Dll的引用几种方式

    右键“引用”,点击“添加引用”(Net Framework项目) 或者右键“依赖项”,点击“添加项目引用” 打开“引用管理器”窗口,切换到“项目”一栏 在右侧列表中,勾选需要引用的项目,然后点击确定 推荐在解决方案文件夹下创建一个专门的文件夹用于存放外部引用的dll 右

    2024年02月02日
    浏览(43)
  • Unity调用微软SpeechLib.Dll的C#类实现语音合成功能

    using System.Collections; using System.Collections.Generic; using UnityEngine; using SpeechLib; public class Speech : MonoBehaviour { // Start is called before the first frame update void Start() { } 将Interop.SpeechLib.dll文件导入Unity,然后把上面的脚本挂载到游戏对象上就能测试语音合成的效果了。 经测试 调用v.Speak这个方

    2024年02月13日
    浏览(51)
  • Visual Studto 2022 如何创建 C++ CLR Windows窗体应用程序

    #include \\\"pch.h\\\" #include \\\"MyForm.h\\\" using namespace System; using namespace ConsoleApplication1; int main(arraySystem::String ^ ^args) {     Windows::Forms::Application::Run( gcnew MyForm());     return 0; }  

    2024年02月03日
    浏览(93)
  • CLR基础全面版-概念、执行模型、托管模块、程序集、FCL

    概念:CLR Common Language Runtime 公共语言运行时 顾名思义,是多编程语言共同使用的运行时 微软创建了很多个面向CLR的语言编译器:C#,C++,F#等 CLR不关心运用什么语言编写源代码,只需要编译器面向CLR 编译器:检查语法,分析源代码确定含义。不管是什么语言都会把代码生成

    2024年02月03日
    浏览(35)
  • 自己开发jlink烧录软件,烧录上位机, C#调用JLinkARM.dll实现软件烧录

    最近需要写一个烧录软件,让工厂可以实现一键烧录。 这里实现了运行一个bat文件进行一键烧录,不想看这部分的可以直接跳到第二部分,不受影响。 由于jlink的自带烧录软件JFlash.exe操作十分繁杂,需要自己开发一个简洁的烧录方法,一番操作发现,可以使用J-Link Commander

    2024年04月11日
    浏览(44)
  • C#开发DLL,CAPL调用(CAPL>> .NET DLL)

    ret为dll里函数返回的值。 在visual studio中建立。

    2024年02月08日
    浏览(42)
  • C# DLL嵌套调用时修改生效

    C# DLL嵌套调用时,需要以被修改的DLL作为最下层,从下往上地重新生成所有DLL才可生效。 DLL1(最下层)代码: DLL2(中间层)代码: 应用程序代码: 实验步骤: 1.在代码无修改的情况下运行应用程序,输出结果为A。 2.修改DLL1动态链接库ConsoleWriteLineSomething方法,使其输出

    2024年01月25日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包