LPVoid到接口参考无效铸造异常



我在施放lpVoid的类时遇到问题,而不是将其重新铸造为接口类。这是简化的代码:

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'.
   }
};

将Eventraiser^施放给Ieventraiser^应该没有问题,因为我以前尝试过。在尝试进行LPVoid对话之前,它运行良好。但是,当我将其投入LPVOID并将其重新铸造给Ieventraiser时,它会引发无效的CastException。我该如何正确地通过LPVoid进行铸件?

将LPVoid指针指向我的非托管班的原因是摆脱重复的标题导入。因此,尽管我注意包括标头文件,但Ieventraiser的标头文件还是以某种方式导入了继承项目。因此,正如Hans Passant在评论中指出的那样,由于不同的组装名称,它会导致铸造问题。我为解决问题所做的工作是将#IFDEF语句添加到Base Project的Ieventraiser标头文件中。喜欢以下内容:

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

然后,我将" base_dll"添加到预处理器定义中。它可以保证将启动启动标题包括一次。另一种选择是使用前向声明,以免将" ieventraiser.h"标头文件添加到未管理的文件标头中。它也被尝试并起作用。

最新更新