非托管方法成员用作托管类中的委托

时间:2013-10-17 23:49:16

标签: callback delegates c++-cli marshalling unmanaged

我有一个项目,我通过集成来自托管DLL的驱动程序,为面向客户的库扩展现有的本机C ++兼容代码功能,这似乎是大多数编组问题的相反方向。由于可以有多个设备使用这个驱动程序,因此每个设备都需要是自己的对象,并具有自己的回调方法。此集成将采用本机包装DLL的形式,该DLL将本机类接口公开给面向客户的库,该库将成员方法回调函数指针的实例传递给DLL。我需要将本机方法成员实例(非静态)作为委托传递给托管包装类。托管包装器类使用GetDelegateForFunctionPointer,它可以编组静态本机指针到委托,但是如果它适用于实例,我找不到任何信息。 GetDelegateForFunctionPointer还为函数指针采用System :: IntPtr参数,但我也不确定System :: IntPtr是否适用于实例,并且在VC ++ 2008中进行编译时,我遇到错误C3867以尝试此操作。

托管包装标题:

//somemanagedclass.hpp
#pragma once

using namespace System;
using namespace ExternalManagedLibrary;

namespace SomeNameSpace
{
   public ref class SomeManagedClass
   {
      public:
         SomeManagedClass();
         ~SomeManagedClass();

         delegate void CallbackHandler(const wchar_t*, int);
         CallbackHandler^ CallbackEvent;

         void RegisterCallback(IntPtr callbackEvent);

      private:
         ExternalManagedClass^ externalManagedClass;

         void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
   };
}

托管包装来源:

//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>

using namespace System;
using namespace Runtime::InteropServices;

namespace SomeNameSpace
{
   SomeManagedClass::SomeManagedClass()
   {
      externalManagedClass = gcnew ExternalManagedClass();
      externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
   }

   SomeManagedClass::~SomeManagedClass()
   {
      externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
   }

   void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
   {
      String^ some_string = String::Copy(e->Value);
      cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
      const wchar_t* p = pinned_string;

      CallbackEvent(pinned_string, some_string->Length);
   }

   void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
   {
      CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
   }
}   

原生包装器界面:

//somenativeinterface.hpp
#ifdef DLL_EXPORT
   #define IMPORT_EXPORT __declspec(dllexport)
#else
   #define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT

typedef void (*NativeCallback)(const unsigned char*, unsigned long);

class IMPORT_EXPORT SomeNativeInterface
{
   public:
      //class factory
      static SomeNativeInterface* Create(void);
      static void Destroy(SomeNativeInterface* clInterface);

      virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};

原生包装标题:

//somenativeclass.hpp
#pragma once

#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>

using namespace SomeNameSpace;

class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
   public:
      SomeNativeClass();
      ~SomeNativeClass();

      void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?

   private:
      NativeCallback fnNativeCallback;
      void OnNativeCallback(const wchar_t* cString, int iSize);
      gcroot<SomeManagedClass^> wrapper;   //warning C4251
};

原生包装来源:

//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>

using namespace System;
using namespace Runtime::InteropServices;

SomeNativeInterface* SomeNativeInterface::Create()
{
   return ((SomeNativeInterface*) new SomeNativeClass());
}

void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
   delete instance;
}

SomeNativeClass::SomeNativeClass()
{
   wrapper = gcnew SomeManagedClass();
}

SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
   std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
   size_t iCharsConverted;
   if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
   {
      if (iCharsConverted > 0xFFFFFFFF)
         iCharsConverted = 0xFFFFFFFF;   //truncate
      fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
   }
}

SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
   fnNativeCallback = fnNativeCallbackInit;
   wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}

0 个答案:

没有答案