【问题标题】:Returning object from C# COM method and memory ownership从 C# COM 方法和内存所有权返回对象
【发布时间】:2015-06-02 08:42:18
【问题描述】:

我已经用 C# 实现了一个 COM 组件:

[ComVisible(true)]
[System.Runtime.InteropServices.Guid("E052BB1C-7ADC-47F4-99E1-9407E2FA0AA2")]
public interface IColorRamps
{
    IColorRamp getColorRamp();
}

[ComVisible(true)]
[Guid("EE47F2F2-0AD9-437C-8815-D570EACF2C07")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ColorRamps.ColorRamps")]
public class ColorRamps : IColorRamps
{
    public IColorRamp getColorRamp() { ... } 
}

我从 C++ 中调用它:

IColorRampPtr colorRamp;
{
    ColorRamps::IColorRampsPtr colorRamps(ColorRamps::CLSID_ColorRamps);
    HRESULT hr = colorRamps->getColorRamp(&colorRamp);
    colorRamp.AddRef(); // Should I do this??
 }

起初我没有调用 AddRef() 并且一切似乎都正常,只是在多次运行此代码后出现“R6025(纯虚函数调用)运行时错误”的奇怪崩溃。

自动生成的 .tlh 文件中的签名是:

virtual HRESULT __stdcall getColorRamp(/*[out,retval]*/ struct IColorRamp * * pRetVal ) = 0;

当在 C++ 中调用这样的函数时,我习惯于函数本身执行 AddRef() 并将内存所有权传递给调用者。在 C# COM 中不是这样吗?

我没有在 ColorRamps.getColorRamp() 中调用 Marshal.AddRef()。

【问题讨论】:

    标签: c# c++ .net com


    【解决方案1】:

    最有可能发生这种情况是因为您 Release() 指针而不是因为 .NET 在返回之前忘记了 AddRef()(提示:.NET 肯定没有忘记这一点)。

    IColorRampPtr 本身就是一个智能指针,你必须使用它,因为你 #imported 是 VC++ 中的 .NET 生成的类型库。因此,您永远不应该在智能指针上调用Release(),因为它会在超出范围时被释放(或者,如果在类成员中使用,则在对象被销毁时)。

    如果您想要一个原始指针,以后必须调用Release(),请使用原始接口指针(例如IColorRamp*)或Detach() the smart pointer。通常,当其范围变得不确定时,您需要一个原始接口指针。如果范围定义明确并且您可以使用智能指针,请将其保留为智能指针。

    【讨论】:

    • 我很确定我没有 Release() 指针。由于它是一个智能指针,我认为它应该照顾好自己。我遇到的崩溃可能来自代码中的其他地方,但事实是,当我调用 AddRef() 时,我无法重现它。我在想纯虚函数调用异常可能来自Runtime Callable Wrapper?
    【解决方案2】:

    来自 MSDN (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.addref%28v=vs.80%29.aspx):

    公共语言运行库管理 COM 的引用计数 对象,因此无需直接使用此方法。在 在极少数情况下,例如测试自定义编组器,您可能会发现它 需要手动操作对象的生命周期。打电话后 AddRef,你必须通过使用这样的方法来减少引用计数 作为 Marshal.Release。不要依赖 AddRef 的返回值,因为它 有时会不稳定。

    值得一看吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-14
      • 2014-04-11
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      相关资源
      最近更新 更多