1

我有一个项目,通过集成来自托管 DLL 的驱动程序,我正在为面向客户的库扩展现有的本机 C++ 兼容代码功能,这对于大多数编组问题来说似乎是相反的方向。由于可以有多个设备使用这个驱动程序,因此每个设备都需要有自己的对象,并具有自己的回调方法。这种集成将采用本机包装 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
}
4

0 回答 0