lpvoid到接口引用无效的强制转换异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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时,它会抛出InvalidCastException。如何正确地通过LPVOID进行铸造?

答案

有一个指向我的非托管类的LPVOID指针的原因是摆脱重复的标头导入。因此,虽然我注意包含头文件,但IEventRaiser的头文件以某种方式导入到固有项目中。因此,正如Hans Passant在评论中指出的那样,由于不同的程序集名称,它会导致转换问题。我为解决这个问题所做的是将#ifdef语句添加到基础项目的IEventRaiser头文件中。如下:

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

然后,我将“BASE_DLL”添加到预处理器定义中。它保证事件提升者标题将被包含一次。另一种方法是使用前向声明,不将“IEventRaiser.h”头文件添加到非托管文件头。它也尝试和工作。

以上是关于lpvoid到接口引用无效的强制转换异常的主要内容,如果未能解决你的问题,请参考以下文章

C# 的无效强制转换异常

通过 UCanAccess 插入时出现“强制转换的字符值无效”错误

检索 scope_identity 时指定的强制转换无效

DataReader:指定的强制转换无效 (Int32)

如何修复 C# 中的“指定强制转换无效”错误?

尝试在空对象引用上调用接口方法“____”[重复]