首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从C# COM方法返回对象和内存所有权

从C# COM方法返回对象和内存所有权
EN

Stack Overflow用户
提问于 2015-06-02 16:42:19
回答 2查看 138关注 0票数 2

我在C#中实现了一个COM组件:

代码语言:javascript
复制
[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++调用这个:

代码语言:javascript
复制
IColorRampPtr colorRamp;
{
    ColorRamps::IColorRampsPtr colorRamps(ColorRamps::CLSID_ColorRamps);
    HRESULT hr = colorRamps->getColorRamp(&colorRamp);
    colorRamp.AddRef(); // Should I do this??
 }

起初,我没有AddRef()调用,除了在多次运行此代码后出现奇怪的"R6025 (纯虚函数调用)运行时错误“之外,一切似乎都正常。

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

代码语言:javascript
复制
virtual HRESULT __stdcall getColorRamp(/*[out,retval]*/ struct IColorRamp * * pRetVal ) = 0;

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

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

EN

回答 2

Stack Overflow用户

发布于 2015-06-02 18:20:19

这很可能是因为你Release()了指针,而不是因为.NET在返回之前忘记了AddRef() (提示:.NET肯定没有忘记这一点)。

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

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

票数 3
EN

Stack Overflow用户

发布于 2015-06-02 17:14:31

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

公共语言运行库为您管理COM对象的引用计数,从而无需直接使用此方法。在极少数情况下,例如测试自定义封送拆收器,您可能会发现有必要手动操作对象的生存期。调用AddRef之后,必须使用诸如Marshal.Release之类的方法递减引用计数。不要依赖AddRef的返回值,因为它有时可能不稳定。

值得一看吗?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30591270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档