lpvoid 到接口引用无效强制转换异常
lpvoid to interface reference invalid cast exception
我在将 class 转换为 LPVOID 以及将其重新转换为接口 class 时遇到问题。这是简化的代码:
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 指针指向我的非托管 class 的原因是为了摆脱重复的 header 导入。因此,尽管我注意包含的 header 文件,但 IEventRaiser 的 header 文件以某种方式导入到继承项目中。因此,正如 Hans Passant 在评论中指出的那样,由于程序集名称不同,它会导致转换问题。我为解决该问题所做的是将 #ifdef 语句添加到基础项目的 IEventRaiser header 文件中。像下面这样:
#ifdef BASE_DLL
#include "IEventRaiser.h"
#endif
然后,我将 "BASE_DLL" 添加到预处理器定义中。它保证事件引发者 header 将被包含一次。另一种选择是使用前向声明不将 "IEventRaiser.h" header 文件添加到非托管文件 header。它也已经过尝试并正在运行。
我在将 class 转换为 LPVOID 以及将其重新转换为接口 class 时遇到问题。这是简化的代码:
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 指针指向我的非托管 class 的原因是为了摆脱重复的 header 导入。因此,尽管我注意包含的 header 文件,但 IEventRaiser 的 header 文件以某种方式导入到继承项目中。因此,正如 Hans Passant 在评论中指出的那样,由于程序集名称不同,它会导致转换问题。我为解决该问题所做的是将 #ifdef 语句添加到基础项目的 IEventRaiser header 文件中。像下面这样:
#ifdef BASE_DLL
#include "IEventRaiser.h"
#endif
然后,我将 "BASE_DLL" 添加到预处理器定义中。它保证事件引发者 header 将被包含一次。另一种选择是使用前向声明不将 "IEventRaiser.h" header 文件添加到非托管文件 header。它也已经过尝试并正在运行。