Search code examples
castingc++-cliclr

lpvoid to interface reference invalid cast exception


I have problems casting a class to LPVOID and than recasting it to interface class. Here is the simplified code:

public interface class IEventRaiser
{
   void fireAppDisconnect()
   // some other methods
}

interface class ISpecificEventRaiser : IEventRaiser
{
   // some specific methods
}

public ref class ManagedItem
{
   ManagedItem()
   {
      eventRaiser = gcnew EventRaiser();
      LPVOID lP = reinterpret_cast<LPVOID>(GCHandle::ToIntPtr(GCHandle::Alloc(eventRaiser)).ToPointer();
      item = new UnmanagedItem(lP);
   }
   // some implementation
   ref class EventRaiser : public ISpecificEventRaiser
   {
      virtual void fireAppDisconnect();
      // other methods
   };

   EventRaiser^ eventRaiser;
   UnmanagedItem* item;
};

public class UnmanagedItem
{
   UnmanagedItem(LPVOID eventRaiser)
   {
      IEventRaiser^ r;
      IntPtr pointer(eventRaiser);
      handle = GCHandle::FromIntPtr(pointer);
      r = safe_cast<IEventRaiser^>(handle.Target); // InvalidCastException : Unable to cast object of type 'EventRaiser' to type 'IEventRaiser'.
   }
};

There should be no problem with casting to EventRaiser^ to IEventRaiser^, because i tried it before. Before trying to LPVOID conversations, it was working fine. But when i cast it into LPVOID and recast it to IEventRaiser, it throws InvalidCastException. How can i do the castings via LPVOID properly?


Solution

  • Reason to have a LPVOID pointer to my unmanaged class was to get rid of duplicate header imports. So, although i pay attention to included header files, IEventRaiser's header file was imported to inhereted project in some way. So, as Hans Passant indicated on comments, it causes a cast problem because of different assembly names. What i did to solve the problem is adding #ifdef statements to base project's IEventRaiser header file includes. Like the following:

    #ifdef BASE_DLL 
    #include "IEventRaiser.h"
    #endif
    

    Then, i added to "BASE_DLL" to preprocessor definitions. It guarantees that the event raiser header will be included once. The other alternative was using forward declarations for not to add "IEventRaiser.h" header file to unmanaged file header. It's also tried and working.