• 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里的主要代码,主要做回调和导出

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Runtime.InteropServices;
    6. namespace CSharpScriptExport
    7. {
    8. // 声明一个回调委托
    9. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    10. public delegate int callback_int_int(int nVal);
    11. public class CCSharpImpl
    12. {
    13. // 声明一个委托字段用于存储回调函数
    14. public callback_int_int absCallback { get; set; }
    15. // 注册回调函数
    16. public void RegCallBack_Abs(callback_int_int fn)
    17. {
    18. absCallback = fn;
    19. }
    20. public void SetInt(int nVal)
    21. {
    22. m_nVal = nVal;
    23. }
    24. public int GetInt()
    25. {
    26. return m_nVal;
    27. }
    28. public int Add(int a, int b)
    29. {
    30. int result = a + b;
    31. // 在方法中调用回调委托,如果已注册
    32. var val= absCallback?.Invoke(a);
    33. if (val.HasValue)
    34. {
    35. result = b + val.Value;
    36. }
    37. return result;
    38. }
    39. public int Subtract(int a, int b)
    40. {
    41. return a - b;
    42. }
    43. private int m_nVal = -5;
    44. }
    45. }

    在CLR的DLL里做包装

    1. #include "pch.h"
    2. //#include "CMainWrapper.h"
    3. #include
    4. using namespace System::Runtime::InteropServices;
    5. #using "..\x64\Debug\CSharpScriptExport.dll"
    6. using namespace CSharpScriptExport;
    7. using namespace System;
    8. namespace CppWrapLibrary {
    9. class CCppWrap
    10. {
    11. public:
    12. virtual int Add(int a, int b) = 0;
    13. virtual int Subtract(int a, int b) = 0;
    14. virtual void RegCallback() = 0;
    15. //第一个"_"表示返回值,第二个表示形参列表
    16. virtual void RegCallback_int_int(int(*fn)(int)) = 0;
    17. virtual ~CCppWrap() = default;
    18. };
    19. public ref class CCppFunWrapper {
    20. public:
    21. CCppFunWrapper(int (*cppFun)(int)) {
    22. m_pCppFun = cppFun;
    23. }
    24. int callFun(int arg) {
    25. return m_pCppFun(arg);
    26. }
    27. private:
    28. int (*m_pCppFun)(int);
    29. };
    30. class CCppWrapImpl : public CCppWrap
    31. {
    32. public:
    33. virtual int Add(int a, int b)
    34. {
    35. return m_CSref->Add(a, b);
    36. }
    37. virtual int Subtract(int a, int b)
    38. {
    39. return m_CSref->Subtract(a, b);
    40. }
    41. virtual void RegCallback() {
    42. }
    43. virtual void RegCallback_int_int(int(*fn)(int)) {
    44. CCppFunWrapper^ funWrapper = gcnew CCppFunWrapper(fn); //将cpp风格的函数指针做包装,使得可以作为委托构造参数
    45. CSharpScriptExport::callback_int_int^ callbackFun = gcnew CSharpScriptExport::callback_int_int(funWrapper,&CCppFunWrapper::callFun); //实例化委托对象
    46. m_CSref->RegCallBack_Abs(callbackFun); //注册
    47. }
    48. CCppWrapImpl() : m_CSref(gcnew CSharpScriptExport::CCSharpImpl())
    49. {
    50. }
    51. // Included for debugging breakpoint instead of using compiler generated default destructor
    52. virtual ~CCppWrapImpl()
    53. {
    54. };
    55. private:
    56. // m_CSref holds a reference to the C# class library.
    57. msclr::gcroot m_CSref;
    58. };
    59. };
    60. // return a pointer to base class CppWrap. CppWrapImpl cannot be declared in unmanaged code
    61. __declspec(dllexport) CppWrapLibrary::CCppWrap* CreateWrapper()
    62. {
    63. return static_cast(new CppWrapLibrary::CCppWrapImpl);
    64. }
    65. //int CMainWrapper::GetInt()
    66. //{
    67. // return 0;
    68. //}
    69. //
    70. //int CMainWrapper::GetInt2()
    71. //{
    72. // return 0;
    73. //}

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

    1. #include
    2. #include "../CSharpExportWrapper/pch.h"
    3. using namespace std;
    4. //extern "C" _declspec(dllexport) int GetInt();
    5. namespace CppWrapLibrary {
    6. class CCppWrap
    7. {
    8. public:
    9. virtual int Add(int a, int b) = 0;
    10. virtual int Subtract(int a, int b) = 0;
    11. virtual void RegCallback() = 0;
    12. virtual void RegCallback_int_int(int(*fn)(int)) = 0;
    13. virtual ~CCppWrap() = default;
    14. };
    15. };
    16. __declspec(dllimport) CppWrapLibrary::CCppWrap* CreateWrapper();
    17. using namespace CppWrapLibrary;
    18. int powM(int a) {
    19. return a*a;
    20. }
    21. int absM(int a) {
    22. return a >= 0 ? a : -a;
    23. }
    24. //note:主函数模拟QT主程序.
    25. // 因为QT不能在CLR中运行,所以需要借助CLR生成的dll交互
    26. // (QT)非托管C++ --> (C++/CLR)托管C++ --> (项目中C#导出的DLL,基于.NET FRAMEWORK)C#
    27. // 即:QT可执行程序->CSharpExportWrapper动态库(CLR)->CSharpScriptExport
    28. int main()
    29. {
    30. /*int a = GetInt();
    31. std::cout <
    32. CCppWrap* pWrapper = CreateWrapper();
    33. if (pWrapper)
    34. {
    35. {//类成员调用
    36. cout << "--------类成员调用-------" << endl;
    37. int x = pWrapper->Add(10, 10);
    38. int y = pWrapper->Subtract(100, 58);
    39. cout << "10 + 10 = " << x << "\n100 - 58 = " << y << endl;
    40. }
    41. {//callback
    42. cout << "--------注册回调:absM--------" << endl;
    43. pWrapper->RegCallback_int_int(absM);
    44. int b = pWrapper->Add(-10, 10);
    45. cout << "absM(-10)+10 = " << b << endl;
    46. cout << "--------注册回调:powM--------" << endl;
    47. pWrapper->RegCallback_int_int(powM);
    48. b = pWrapper->Add(-10, 10);
    49. cout << "powM(-10) + 10 = " << b << endl;
    50. }
    51. delete pWrapper;
    52. }
    53. system("pause");
    54. }

    运行结果

    具体工程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博客

  • 相关阅读:
    京东数据分析(京东数据采集):2023年10月京东平板电视行业品牌销售排行榜
    MATLAB嵌套if语句||MATLAB switch语句
    CSS显示模式
    “先进”的飞书为何搞不定钉钉?
    LeetCode 2385.感染二叉树需要的总时间:两次搜索(深搜 + 广搜)
    恢复IDEA误删除的git提交,提交被删除,尝试恢复提交
    (附源码)ssm失物招领平台 毕业设计 271621
    BGP服务器
    《痞子衡嵌入式半月刊》 第 60 期
    Operations Management: What Is It and Why Does It Matter?
  • 原文地址:https://blog.csdn.net/Charles_ke/article/details/133957818