简单讲讲需求: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
- 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
m_CSref; - };
- };
-
-
- // return a pointer to base class CppWrap. CppWrapImpl cannot be declared in unmanaged code
- __declspec(dllexport) CppWrapLibrary::CCppWrap* CreateWrapper()
- {
- return static_cast
(new CppWrapLibrary::CCppWrapImpl); - }
-
-
- //int CMainWrapper::GetInt()
- //{
- // return 0;
- //}
- //
- //int CMainWrapper::GetInt2()
- //{
- // return 0;
- //}
在C++主程序里作为调用方
-
- #include
- #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();
-
- 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