【问题标题】:Which COM smart pointer classes to use?使用哪些 COM 智能指针类?
【发布时间】:2011-08-03 20:21:27
【问题描述】:

我对 C++ 编程的 COM 智能指针类的选择感到困惑:

我知道有三个四个:

  • CCOMPtr 来自 ATL
  • _com_ptr_t 来自MS Com Support Classes
  • TComInterface(因为我使用的是 C++Builder 2009)
  • CCOMQIPtr,(我之前忘记了)

我已经阅读了前两者的错误与异常处理差异,但TComInterface 似乎完全没有记录。据我所知,前两个似乎都有问题或“意外”行为。

理想情况下,我想要一些干净且现代的 C++,但据我所知,boost::com 并不存在...

我需要控制来自其他供应商的应用程序。它们通过 TLB 文件提供 COM 接口。

【问题讨论】:

  • 你想做什么? COM 自动化到另一个应用程序?托管 ActiveX 控件?为您的应用提供 COM 接口?
  • 您可能还想讨论 BSTR 智能包装器。
  • 已经有一段时间了,但我记得我很确定使用 CComPtr。
  • @Kenny,以上任何一个都可以完成这项工作,它们大约 80% 相同。
  • five.

标签: c++ com c++builder


【解决方案1】:

正如kenny 提到的,您可以使用CComPtr 来管理指向COM 接口的指针。这个类有据可查(参见msdn)并使用自动引用计数,我想,你想要什么。

OTOH,Rob 问题很重要:你真的使用 COM 接口吗?对于指针,您可以使用来自STLboost 库的智能指针,它们(通常)比CComPtr 更好。

【讨论】:

  • @maverick - 是的,我需要 COM :-(
【解决方案2】:

我使用了前两个,CComPtr 和 _com_ptr_t。

听起来您已经了解了错误和异常处理的区别,因此请选择您最喜欢的一个,或者与您代码中的其余错误处理最一致的那个。

【讨论】:

    【解决方案3】:

    如果您使用类型库导入的东西,它将根据_com_ptr_t 和相关的 COM 支持类生成代码。如果您只是使用这些库中的内容,请继续使用它们。

    如果您正在编写基于 ATL 的代码,请使用 CCOMPtr 和其他基于 ATL 的类。

    如果您需要混合搭配这两种类型,事情可能会变得很糟糕,但您可能应该对这两种类型都感到满意,并使用对您当时所做的任何事情最有意义的那个。

    好消息是您拥有所有这些东西的源代码,因此您不必只依赖文档(自从 .NET 出现以来,文档并没有得到太多关注)。

    【讨论】:

    • 混搭还不错;您可以来回传递原始接口指针。此外,CComPtr(与 ATL 的其余部分一起)对于 ActiveX 包含非常方便。 ATL 不仅适用于 COM 服务器。
    【解决方案4】:

    既然您要求“干净和现代”的 C++ 风格,并以 boost 为例,我将再添加两个:std/boost::shared_ptrboost::intrusive_ptr。 intrusive_ptr 显然是更自然的选择,因为 COM 对象具有侵入式引用计数机制。 shared_ptr 也同样有效,您只需要使用一个调用IUnknown::Release() 的自定义删除器,以及一个执行IUnknown::AddRef() 并返回智能指针的小对象生成器函数。

    我通常使用intrusive_ptr,所以我将更详细地解释这一点。首先,当然,必须为所有IUnknowns 实现 intrusive_ptr_add_ref 和 intrusive_ptr_release。 intrusive_ptr 构造函数已经有一个方便的功能,可以跳过添加另一个引用,因为许多 COM 函数将为您执行 AddRef()

    现在这种方法存在一个问题:intrusive_ptr 不像其他一些 COM 指针那样暴露其底层裸指针。这是一个问题,因为创建 COM 对象的常用方法是将指针传递给另一个对象中的某个创建函数的指针。由于您无法将 intrusive_ptr 传递给这些函数,因此您最终会得到用于初始化 intrusive_ptr 的笨拙的临时裸指针。这不是很优雅,更不用说异常安全了(如果你完全需要 COM 代码,它自然不会抛出异常。不过我将 COM 错误转换为异常。)

    所以我在这里做的是使用另一个工具函数,它转换一个函数,该函数接受任何 com 函数并返回一个可调用的,其中任何作为指向 T 的指针的参数可以是那个或对intrusive_ptr。其他任何东西就像“输入功能”一样。然后这些函数为我完成 T** 和 intrusive_ptr& 之间的所有转换。例如,HRESULT CreateBuffer(IBuffer** bufferOut, int size) 成为带有签名HRESULT CreateBuffer(instrusive_ptr<IBuffer>& bufferOut, int size) 的可调用对象。除非您有代码生成器,有足够的耐心,或者我认为可变参数模板,否则为“所有” arities 编写它们有点乏味。但是一旦你有了它们,它实际上让使用 COM 变得非常好。

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 2018-08-31
      • 2017-07-18
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多