【发布时间】:2017-12-16 11:42:51
【问题描述】:
我在将类转换为 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 进行铸件?
【问题讨论】:
-
亲爱的@HansPassant,它将一直存在到应用程序的生命周期中,我将在析构函数上调用handle.free()。我试图将引用包装为 IEventRaiser,但它引发了相同的异常。喜欢以下; ISpecificEventRaiser^ sEventRaiser = (ISpecificEventRaiser^)eventRaiser; lp = reinterpret_cast
(GCHandle::ToIntPtr(GCHandle::Alloc(safe_cast (sEventRaiser ))).ToPointer(); -
将这段代码 sn-p 修改成可以编译的形状是一项艰巨的工作。当我尝试时,无论哪种方式都可以正常工作,演员表不是问题。可能的错误是您对接口类型有多个定义。当您在 .h 文件中声明它并将它包含在属于两个不同项目的源文件中时,往往会发生这种情况。 .NET 中的类型标识不仅由命名空间和标识符名称定义,它还包括它所在的程序集的全名。使用程序集引用代替,因此只有一个接口定义。
-
想一想,你之前已经遇到过这个问题了。您在previous question 中犯了完全相同的错误。
-
亲爱的@HansPassant,我在最后一个问题后删除了 .h 文件。所以,接口类不应该被定义两次。但是,是的。看来这是一个组装问题。我打印了 IEventRaiser 句柄的组件名称,它是继承的组件名称!但我无法理解这怎么可能。在继承的项目中,基础项目只有一个头文件,并且仅用于本地类的头文件。并且该头文件不包含任何托管类型头文件。所以,接口类不应该被原生包含。