C#中使用托管C++类,委托调用,以供托管C++类的成员函数回调的实现方式

       在网上有很多资料,说的是C#使用C++动态库的全局函数实现C++回调C#的实现;但本文主要是介绍在托管C++的原C++类中回调C#的实现

       先讲一下全局函数的实现,下面再讲托管类的成员函数的实现;

第一步:随便创建一个C++的MFC的动态库Test,刚开始里面只是系统生成的一些代码,这里忽略;

第二步:然后我们再里面定义一个函数指针的类型,代码如下,这里只是示意方法步骤,参数列表和返回类型可以自己设置;

          typedef void ( WINAPI *callback)();

第三步:随便定义一个导出函数;

          void WINAPI callFunc(callback fn)
          {
                 AfxMessageBox(_T("这是C++ 的动态库 导出函数"));
                 fn(); 
           }

第四步:将C++的函数导出,代码如下;

          extern "C" __declspec(dllexport) void WINAPI callFunc(callback fn);

       如此,C++动态库的部份就完成,编译生成Test.dll文件即可;

第五步:在当前解决方案中,添加一个C#的WPF应用程序;

第六步:在C#中定义一个委托,要求与C++下的回调函数类型一致,代码如下

          public delegate void callback();

第七步:在C#中声明外部的C++导出方法,参照前面第三步的函数样式

          [DllImport("Test.dll")] static extern void callFunc(callback fn);

第八步:实现第六步声明的委托所代表的回调函数,代码如下

          public static void callbackImpl()
         {
               MessageBox.Show("回调到了C#");
          }

第九步:在C# WPF界面添加一个按钮,并添加按钮的单击事件,在单击事件中调用C++的导出函数,代码如下

          private void TestDynamicC_Click(object sender, RoutedEventArgs e)
          {
                  callFunc(new callback(callbackImpl));
          }

        如此便可先调用C++的导出函数,导出函数再回调C#的callbackImpl函数了;

C#调用非托管代码有四种实现方式:

       1. COM调用;

       2. Dllimport方法调用(直接调用从DLL导出的函数)

       3. 加载托管了的非托管动态连接库

       4. 直接执行机器码

       以上都正常的回调实现方式(C++全局接口函数),可是如果C++的动态库是封装的类,且C++类再以托管类的方式包装成托管代码,以供C#直接使用托管类,如要在托管类实现C#传入回调函数到C++,C++再回调C#,使用方法3托管的方式便不可实现了(这个问题困扰了我三天了),到最后才想了用间接的方式实现托管的回调,上面所讲的实现方式为第二种Dllimport, 具体过实现过程如下所示;

第一步:按照以上方法,创建C++动态库,定义函数指针和导出函数

         typedef void ( WINAPI *callback)();

         extern "C" __declspec(dllexport) void WINAPI callFunc(callback fn);

         void WINAPI callFunc(callback fn)
         {
               AfxMessageBox(_T("C++ 的动态库"));
               fn();
          }

第二步:定义一个函数指针callback类型的静态变量

        static callback oTestCall = NULL;

        并将第一步的fn();替换成oTestCall = fn;即导出函数的参数赋值给静态的函数指针变量;

第三步:在C++的动态库项目中定义C++的托管类,代码如下,此类可以在C#项目中当做正常的托管类使用,另外,在此类中,可以直接定义C++的类的对象(这才是托管C++类的终极目的),再用C++的对象,包装新的托管接口调用C++对象的成员函数,这就实现了C++类到C#类的托管,将MFC项目的属性->配置性性->常规->公共语言运行时支持设置为公代语言运行时支持(/clr),再编译生成Test.dll动态库文件,具体托管时C#与C++的类型对应表,请各位读者再去查找其它资料,这个网上有很多的,

        #pragma once
        using namespace System;
        using namespace System::Collections::Generic;
        using namespace System::Runtime::InteropServices;

        namespace TC_Interface
        {
              public ref class CTableCtrl
             {
                  public:

                  void TestCallBack()
                  {
                         AfxMessageBox(_T("托管C++的方式"));

                         oTestCall();
                   }
              };
        }

第四步:在C#中做以下相关的处理

          1. 在解决方案资源管理器中展开C#项目,右键单击引用,添加引用-》前面创建的C++的动态库项目,添加完成后,在引用项目下面会列出项目引用的资源,其中就有Test,展开后可看到里面的细节;

        //2. 定义委托
        public delegate void callback();

        //3. 声明C++的外部方法
        [DllImport("Test.dll")] static extern void callFunc(callback fn);

        //4. 实现回调函数
        public static void callbackImpl()
        {
            MessageBox.Show("回调到了C#");
        }

第五步:在C#中定义委托变量和C++托管类的变量

        callback oCallBack;
        CTableCtrl oTable = new CTableCtrl();

第六步:在C#中随便定义一个函数,将委托(回调函数)设置到C++中的全局静态函数指针,代码如下,此一步要在使用回调之前调用,

        private void TestDynamicC_Click(object sender, RoutedEventArgs e)
        {
           oCallBack = new callback(callbackImpl);
            //4. 调用动态库的C++导出函数
            callFunc(oCallBack);
        }

第七步:在C#中调用测试回调函数

        private void TestManageC_Click(object sender, RoutedEventArgs e)
        {

            //在C++端的TestCallBack中调用全局静态的函数指针,即实现了C#的回调
            oTable.TestCallBack();
        }

 

写这么一篇文章好累,好费时间,请尊重原创,转载注明出处;

作者:甘敏

 

 

 

 

 

 

 

   

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值