我在将类转换为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'.
}
};
将事件转换到IEventRaiser ^应该没有问题,因为我之前尝试过。在尝试LPVOID对话之前,它工作正常。但是当我将它转换为LPVOID并将其重新转换为IEventRaiser时,它会抛出InvalidCastException。如何通过LPVOID正确地进行铸造?
答案 0 :(得分:0)
有一个指向我的非托管类的LPVOID指针的原因是摆脱重复的标头导入。因此,虽然我注意包含头文件,但IEventRaiser的头文件以某种方式导入到固有项目中。因此,正如Hans Passant在评论中指出的那样,由于不同的程序集名称,它会导致转换问题。我为解决这个问题所做的是将#ifdef语句添加到基础项目的IEventRaiser头文件中。如下所示:
#ifdef BASE_DLL
#include "IEventRaiser.h"
#endif
然后,我将“BASE_DLL”添加到预处理器定义中。它保证事件提升者标题将被包含一次。另一种方法是使用前向声明,不将“IEventRaiser.h”头文件添加到非托管文件头。它也尝试过并且正在工作。