1

私はマネージ DLL からドライバーを統合することによって顧客向けライブラリの既存のネイティブ C++ 互換コード機能を拡張しているプロジェクトを持っていますが、これはほとんどのマーシャリングの質問とは反対の方向のようです。この 1 つのドライバーを使用する複数のデバイスが存在する可能性があるため、各デバイスは独自のコールバック メソッドを持つ独自のオブジェクトである必要があります。この統合は、ネイティブ クラス インターフェイスを顧客向けライブラリに公開するネイティブ ラッパー 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