2014年2月21日 星期五

Native C++ and C# Bridge

C#有時候因為效能因素,需要和原生C++做溝通,這時候必須透過C++/Cli這個Bridge來做轉換,將受到Manage的Object轉換為Native的Object.
  •  
如架構圖所示,C#可以透過C++/Cli的介面操作,而再由C++/Cli再將Manage的介面轉換為Native的介面.最後NativeC++再直接使用由C++/Cli所提供的Native介面 (此時C++/Cli所提供的Native介面就不能包含Manage的Code)
  •  
下圖為架構圖:

Fig 1. 架構圖
而在實際的作法上,可以先使用C++/Cli Create一個Native的.h檔案,然後宣告一個無型別指標(Void*)用來存放C#的物件.再透過C++/Cli使用ManagePointer(^) new出一個C#的物件,並將Native Pointer(*)指向C# Object(^).
  •  
這時候,不管Native C++要使用任何的C#function,只要先將NativePointer(*)轉換成ManagePointer(^)就可以操作C#了.
  •  
而C#若要Send Event過去給Native C++,一樣需要先透過C++/Cli將C#的 EventHandle加入Manage的Event,然後在轉成Native的Event丟給Native C++.
  •  
基本上轉換的過程中,都是透過ManagePointer和NativePointer互傳.
  •  
下圖為運作架構圖:

Fig 2. 運作架構圖
最後附上簡易的 Bridge Sample Code
Sample Code
------------------------Native C PlusPlus.h----------------------
define DECLSPECIFIER __declspec(dllexport)
define EXPIMP_TEMPLATE

typedef void(__stdcall *CallbackType)(void*, void*);
namespace NativeToMangeBridge
{
     [event_source(native)]
     class DECLSPECIFIER Bridge
     {
          Public:
               void callCSfunction(std::stringmessage);
               __event void OnEventInvoke(CallbackType callback);
               void * m_ptr;
     }
}
----------------------------------------------------------------------

------------------------Native/Cli.cpp-----------------------------
#include "Native C Plus Plus .h"
namespace NativeToMangeBridge
{
      Bridge::Bridge()
      {
              CSharpClass^ _CSInstances = gcnew CSharpClass();
              m_impl= GCHandle::ToIntPtr(GCHandle::Alloc(_CSInstances)).ToPointer();
      }

      voidBridge::callCSfunction(std::string message)
     {
             GCHandle handle = GCHandle::FromIntPtr(IntPtr(m_ptr));
             CSharpClass^ _CSPtr = safe_cast<CSharpClass^>(handle.Target);
             String^ MgrMessage = gcnew String(message.c_str());
             _CSPtr->CSfunction(MgrMessage);
     }
}
----------------------------------------------------------------------

------------------------Cli.cpp--------------------------------------
namespace NativeToMangeBridge
{
     Cli::Bridge(Bridge _NativeCPlus)
     {
  _CSPtr->InfoChangeEvent += gcnew EventHandler<CSharpClass::EventHandler^>(this, &Cli::function);
     }

     Cli::function()
     {
        __raise NativeCPlus->OnEventInvoke(_Callbackfunction);
     }
}
----------------------------------------------------------------------

沒有留言:

張貼留言