this是问题的根源。我的回答被删除,提示开始一个新问题。所以,我们走了:
我想将this
的托管引用传递给非托管代码。然后从非托管回调中调用托管回调。
public ref class CReader
使用私有字段
private:
[...]
void *m_pTag;
[...]
在托管类的构造函数中,我像这样初始化m_pTag
:
m_pTag = new gcroot<CReader ^>(this);
稍后,我将此void *m_pTag
传递给非托管代码。如果调用了非托管回调,我将void *m_pTag
转发回托管引用并调用托管回调
(*(gcroot<CReader ^>*)pTag)->MANAGEDCALLBACKFUNCTION
如果DLL在另一个AppDomain下使用,则抛出异常。调试器在gcroot.h
在线
// don't return T& here because & to gc pointer not yet implemented
// (T should be a pointer anyway).
T operator->() const {
// gcroot is typesafe, so use static_cast
return static_cast<T>(__VOIDPTR_TO_GCHANDLE(_handle).Target);
}
Cannot pass a GCHandle across AppDomains.
我的问题是,我该怎么办?
诚恳,
塞巴斯蒂安
====================编辑====================
我现在能够重现这个问题。我拍了一些截图,以显示问题。
问题是,回调中value
- 结构gcroot
的成员是空的。
谢谢。
塞巴斯蒂安
====================编辑====================
推。
答案 0 :(得分:1)
gcroot&lt;&gt; C ++类是一个使用GCHandle类的包装器。构造函数调用GCHandle.ToIntPtr()将句柄转换为不透明指针,您可以安全地将其存储为非托管结构或C ++类的成员。
然后,使用GCHandle.FromIntPtr()方法将该原始指针转换回句柄。 GCHandle.Target属性为您提供了托管对象引用。
GCHandle.FromIntPtr()确实会失败,通用异常消息是“无法通过AppDomains传递GCHandle”。此消息仅指出此失败的常见原因,它假定GCHandle用于安全代码并且使用不正确。
消息不涵盖了在不安全代码中失败的最常见原因。由于堆损坏,代码总是因不可诊断的异常而死亡。换句话说,gcroot&lt;&gt;被任意值覆盖的C ++类或结构的成员。其中当然是GCHandle.FromIntPtr(),CLR无法再从垃圾指针值找回句柄。
您可以通过诊断任何堆损坏问题的方式诊断此错误。首先要确保你得到一个好的repro,这样你就可以可靠地绊倒异常。你在gcroot成员上set a data breakpoint。当成员被不恰当地写入时,调试器会自动中断,调用栈会让你知道为什么会发生这种情况。