【问题标题】:How does one wrap errors when calling COM in C++?在 C++ 中调用 COM 时如何包装错误?
【发布时间】:2012-04-27 09:23:12
【问题描述】:

要遵循典型的 COM 程序,无论何时发生任何错误,都必须执行以下操作:

  1. 检查HRESULTFAILED 或类似的,看看是否发生错误。
  2. 创建一个变量来保存IErrorInfo(通常是CComPtr<IErrorInfo>
  3. 致电::GetErrorInfo(0, &var)
  4. Get the human readable version of that by calling IErrorInfo::GetDescription.
  5. BSTR 转换为std::wstring
  6. std::wstring 转换为某种形式的char const*
  7. 抛出一个用户定义的异常类型,它派生自std::exception,它公开了上面的第 1、5 和 6 位。

这一切看起来像是很多样板文件,几乎必须绕过 COM 中的每个函数调用。

我知道 MSVC++ 编译器提供了一大堆东西让 COM 更容易搞乱,例如 ATL,以及编译器特定的 COM 扩展 _com_error_com_raise_error 和类似的,但我不知道如何使用这些,或者如果它们甚至打算由用户代码使用。

是否有任何典型的策略用于以异常安全和竞争条件安全的方式管理这种复杂性?

【问题讨论】:

  • 从#import 指令开始,其余部分自动到位。
  • @HansPassant:我没有相关目标的类型库。 (我只有wbemidl.h
  • 那么fuggedaboudid,你得自己包起来。只需编写一个 CheckHR() 函数即可。
  • @HansPassant:是的,我可以自己包装这个,而不需要太多的努力;但是,如果在使用大量 COM 的人中已经有一种半标准的方法来做这件事,我想用典型的方式来做,而不是发明新的东西。
  • 为什么是第 6 步? std::exception 不需要 const char*

标签: c++ windows visual-c++ com error-handling


【解决方案1】:

恐怕没有为您提供半标准的方法,即使您查看 msdn 上的示例应用程序和 api 使用情况,它们都表明您必须手动进行所有繁琐的 HResult 检查,检查是否IPtr 是有效的,等等。你必须编写自己的函数来包装所有这些,这样你就不会重复代码,这应该不是问题。

【讨论】:

    【解决方案2】:

    “显而易见”的解决方案是ComException。它几乎可以处理所有步骤 - 您只需要获取 ctor 的 HRESULT 并抛出结果对象(步骤 1 和 7)。

    你甚至可以写

    HRESULT check(HRESULT hr)
    {
      if(FAILED(hr)) throw ComException(hr);
      return hr; // Success comes in different forms. 
    }
    

    为您完成第 7 步。例如。 check(pUnk->QueryInterface(MyID, &pMyIf));

    【讨论】:

    • @AlexandreC。 : 那会发生在ComException::ComException(HRESULT)
    • ComException 如何检索指向 IErrorInfo 的指针?您必须以某种方式将指针传递给它,该指针指向您首先调用该函数的接口,不是吗?
    • @AlexandreC。 :不,that's done via ::GetErrorInfo
    猜你喜欢
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多