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

编程入门 行业动态 更新时间:2024-10-25 08:16:05

qt采用C++/CLI 方式调用C#dll的封装方法(<a href=https://www.elefans.com/category/jswz/34/1765488.html style=高阶应用)"/>

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

简单讲讲需求: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 destructorvirtual ~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;}{//callbackcout << "--------注册回调: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下载链接:

参考资源:

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博客

更多推荐

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

本文发布于:2023-12-06 03:36:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1666325.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:高阶   方式   方法   qt   CLI

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!