【问题标题】:Passing managed reference (this) to unmanaged code and call managed callback将托管引用 (this) 传递给非托管代码并调用托管回调
【发布时间】:2014-03-14 08:41:49
【问题描述】:

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.

我的问题是,我该怎么办?

此致,

塞巴斯蒂安

==================== 编辑====================

我现在能够重现该问题。我已经截取了一些屏幕截图来显示问题。

1st screenshot: constructor

snd screenshot: callback

问题是,回调中结构体gcrootvalue-member是空的。

谢谢。

塞巴斯蒂安

==================== 编辑====================

推。

【问题讨论】:

    标签: reference unmanaged managed command-line-interface


    【解决方案1】:

    gcroot C++ 类是使用 GCHandle 类的包装器。构造函数调用 GCHandle.ToIntPtr() 将句柄转换为不透明指针,您可以安全地将其存储为非托管结构或 C++ 类的成员。

    然后,转换之后,使用 GCHandle.FromIntPtr() 方法将该原始指针转换回句柄。 GCHandle.Target 属性将托管对象引用返回给您。

    GCHandle.FromIntPtr() 确实会失败,一般的异常消息是“无法通过 AppDomains 传递 GCHandle”。此消息仅指出失败的常见原因,它假设 GCHandle 用于安全代码并且只是使用不正确。

    该消息涵盖了在不安全代码中失败的最常见原因。由于堆损坏,代码总是因无法诊断的异常而死掉。换句话说,C++ 类或结构的 gcroot 成员被任意值覆盖。这当然会导致 GCHandle.FromIntPtr() 失败,CLR 无法再从垃圾指针值中找到句柄。

    您诊断此错误的方式与诊断任何堆损坏问题的方式相同。您首先确保您获得了良好的重现,以便您可以可靠地触发异常。你在 gcroot 成员上set a data breakpoint。当成员写入不当时,调试器会自动中断,调用堆栈可以让您很好地了解为什么会发生这种情况。

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 1970-01-01
      • 2013-08-24
      • 2015-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      • 2020-08-26
      相关资源
      最近更新 更多