qt采用C++/CLI 方式调用C#dll的封装方法(高阶应用)

5 篇文章 0 订阅

简单讲讲需求:cpp作为主程序,c#作为第三方程序被调用,并且需要在c#代码里调用主程序里的方法

C#写的dll是没有dllMain入口函数的,是一种中间语言,需要.Net运行时进行做本地化工作,因此如果要调用C#写的dll,需要依赖.Net运行时,然而Qt中还无法直接调用.Net运行时,而且Qt本身的moc机制与.Net运行时天然冲突,需要CLI这一层壳

调用流程:

(QT)非托管C++ --> (C++/CLR)托管C++ --> (项目中C#导出的DLL,基于.NET FRAMEWORK)C#

网上c#调c++的一大堆,但是反过来的却寥寥无几。有的也很简单,实际应用中,不仅需要导出类,还需要传递函数指针作为回调

以下为C#DLL里的主要代码,主要做回调和导出

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CSharpScriptExport
{
    // 声明一个回调委托
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int callback_int_int(int nVal);

    public class CCSharpImpl
    {
        // 声明一个委托字段用于存储回调函数
        public callback_int_int absCallback { get; set; }

        // 注册回调函数
        public void RegCallBack_Abs(callback_int_int fn)
        {
            absCallback = fn;
        }

        public void SetInt(int nVal)
        {
            m_nVal = nVal;
        }

        public int GetInt()
        {
            return m_nVal;
        }

        public int Add(int a, int b)
        {
            int result = a + b;

            // 在方法中调用回调委托,如果已注册
            var val=  absCallback?.Invoke(a);
            if (val.HasValue)
            {
                result = b + val.Value;
            }
            return result;
        }

        public int Subtract(int a, int b)
        {
            return a - b;
        }
        private int m_nVal = -5;
    }
}

在CLR的DLL里做包装

#include "pch.h"
//#include "CMainWrapper.h"

#include <msclr\gcroot.h>
using namespace System::Runtime::InteropServices;

#using "..\x64\Debug\CSharpScriptExport.dll"
using namespace CSharpScriptExport;

using namespace System;

namespace CppWrapLibrary {
    class CCppWrap
    {
    public:
        virtual int Add(int a, int b) = 0;

        virtual int Subtract(int a, int b) = 0;

        virtual void RegCallback() = 0;
        //第一个"_"表示返回值,第二个表示形参列表
        virtual void RegCallback_int_int(int(*fn)(int)) = 0;
        virtual ~CCppWrap() = default;
    };

    public ref class CCppFunWrapper {
    public:
        CCppFunWrapper(int (*cppFun)(int)) {
            m_pCppFun = cppFun;
        }
        int callFun(int arg) {
            return m_pCppFun(arg);
        }
    private:
        int (*m_pCppFun)(int);
    };

    class CCppWrapImpl : public CCppWrap
    {
    public:
        virtual int Add(int a, int b)
        {
            return m_CSref->Add(a, b);
        }

        virtual int Subtract(int a, int b)
        {
            return m_CSref->Subtract(a, b);
        }

        virtual void RegCallback() {

        }

        virtual void RegCallback_int_int(int(*fn)(int)) {
            CCppFunWrapper^ funWrapper = gcnew CCppFunWrapper(fn); //将cpp风格的函数指针做包装,使得可以作为委托构造参数
            CSharpScriptExport::callback_int_int^ callbackFun = gcnew CSharpScriptExport::callback_int_int(funWrapper,&CCppFunWrapper::callFun);  //实例化委托对象
            m_CSref->RegCallBack_Abs(callbackFun);               //注册
        }

        CCppWrapImpl() : m_CSref(gcnew CSharpScriptExport::CCSharpImpl())
        {
        }

        // Included for debugging breakpoint instead of using compiler generated default destructor
        virtual ~CCppWrapImpl()
        {
        };

    private:
        // m_CSref holds a reference to the C# class library.
        msclr::gcroot<CSharpScriptExport::CCSharpImpl^> m_CSref;
    };
};


// return a pointer to base class CppWrap.  CppWrapImpl cannot be declared in unmanaged code
__declspec(dllexport) CppWrapLibrary::CCppWrap* CreateWrapper()
{
    return static_cast<CppWrapLibrary::CCppWrap*>(new CppWrapLibrary::CCppWrapImpl);
}


//int CMainWrapper::GetInt()
//{
//    return 0;
//}
//
//int CMainWrapper::GetInt2()
//{
//    return 0;
//}

在C++主程序里作为调用方


#include <iostream>
#include "../CSharpExportWrapper/pch.h"
using namespace std;

//extern "C" _declspec(dllexport) int GetInt();
namespace CppWrapLibrary {
    class CCppWrap
    {
    public:
        virtual int Add(int a, int b) = 0;

        virtual int Subtract(int a, int b) = 0;

        virtual void RegCallback() = 0;
        virtual void RegCallback_int_int(int(*fn)(int)) = 0;

        virtual ~CCppWrap() = default;
    };
};

__declspec(dllimport) CppWrapLibrary::CCppWrap* CreateWrapper();

using namespace CppWrapLibrary;


int powM(int a) {
    return a*a;
}

int absM(int a) {
    return a >= 0 ? a : -a;
}

//note:主函数模拟QT主程序.
//      因为QT不能在CLR中运行,所以需要借助CLR生成的dll交互
//     (QT)非托管C++ --> (C++/CLR)托管C++ --> (项目中C#导出的DLL,基于.NET FRAMEWORK)C#
//      即:QT可执行程序->CSharpExportWrapper动态库(CLR)->CSharpScriptExport
int main()
{
    /*int a = GetInt();
    std::cout <<a<< "\nHello World!\n";*/

    CCppWrap* pWrapper = CreateWrapper();
    if (pWrapper)
    {
        {//类成员调用
            cout << "--------类成员调用-------" << endl;
            int x = pWrapper->Add(10, 10);
            int y = pWrapper->Subtract(100, 58);
            cout << "10 + 10 = " << x << "\n100 - 58 = " << y << endl;
        }
        {//callback
            cout << "--------注册回调:absM--------" << endl;
            pWrapper->RegCallback_int_int(absM);
            int b = pWrapper->Add(-10, 10);
            cout << "absM(-10)+10 = " << b << endl;

            cout << "--------注册回调:powM--------" << endl;
            pWrapper->RegCallback_int_int(powM);
            b = pWrapper->Add(-10, 10);
            cout << "powM(-10) + 10 = " << b << endl;
        }
        delete pWrapper;
    }
    system("pause");
}

运行结果

具体工程Demo下载链接:https://download.csdn.net/download/Charles_ke/88453493

参考资源:

1.How to use C# objects returned in QT. - Microsoft Q&A

2.Lesson 15: Function Pointers and Delegates

3.QT(C++)如何调用C#的动态链接库DLL_qt c++ 调用c# dll_傻傻的小幸福go的博客-CSDN博客

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt C++是一种跨平台的图形用户界面开发框架,而深度学习是一种机器学习技术,通过神经网络模型进行高级特征学习和处理。在Qt C++中,我们可以使用深度学习方法调用摄像头进行人脸识别。 首先,我们需要准备一个训练好的深度学习模型,用于人脸识别。这个模型通常是在大规模人脸数据集上进行训练的,以获得较高的准确性。 然后,在Qt C++中,我们可以通过调用摄像头的API获取视频帧。每一帧都可以作为输入,传递给深度学习模型进行人脸识别。 在每一帧中,我们可以使用图像处理技术来进行预处理,以提高人脸识别的准确性。例如,我们可以进行人脸检测,将图像中的人脸区域提取出来,然后对图像进行归一化和预处理操作,以适应深度学习模型的输入要求。 接下来,我们可以将预处理后的图像数据输入到深度学习模型中,通过前向传播得到模型的输出。输出通常是一个包含人脸特征的向量或特征描述符。 最后,我们可以比较模型输出的特征向量与已知的人脸特征向量进行匹配,以确定人脸的身份。这可以通过比较特征向量之间的相似性来实现。 总的来说,使用Qt C++调用摄像头进行人脸识别,我们需要准备一个训练好的深度学习模型,并在每一帧中进行图像处理和预处理,然后将预处理的图像数据输入到模型中,得到模型的输出特征向量,最后进行人脸身份的匹配。这样可以实现在Qt C++中使用深度学习方法进行人脸识别的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值