ABI 是否保留了比 HRESULT 更多的错误信息?

Does the ABI persist any more error information than an HRESULT?

在将常规 C++ class 移植到 Windows 运行时 class 时,我遇到了一个相当重要的障碍。我的 C++ class 通过抛出自定义错误对象来报告某些错误情况。这允许客户端方便地过滤异常,记录在 public 界面中。

我似乎无法找到一种可靠的方法来通过 ABI 传递足够的信息以使用 Windows 运行时复制相同的保真度1。假设 HRESULT 是唯一的通用错误报告信息,我评估了以下选项:

  1. 'obvious'选择:将异常条件映射到任何预定义的HRESULT values。虽然这在技术上可行(大概),但在调用站点无法区分源自实现的错误和源自实现的被调用方的错误。
  2. 发明自定义 HRESULT。如果 this layout 仍然适用于 Windows 运行时,我可以很容易地设置 Customer 位并疯狂使用 my 27比特值的错误代码表示。这行得通,直到其他人也这样做。我不知道有什么方法可以将 HRESULT 归因于接口,这将解决这种歧义。
  3. 即使上述任何一个都可以按预期工作,抛出 hresult_errors as prescribed, the call site would still be at the mercy of the language projection. While C# seemingly allows to pass any System.Exception(-derived) error object across the ABI, and have them re-thrown at the call site, C++/WinRT only supports some 14 distinct exception types (see throw_hresult)。

由于这些选项都不允许足够完整的错误信息通过 ABI,看来 HRESULT 可能还不够。 Windows 运行时是否有任何配置允许额外的(任意)错误信息通过 ABI?


1 我对传递实际的 C++ 异常并不完全感兴趣。相反,我正在寻找一种允许客户以自然方式 唯一地 识别记录在案的错误情况的方法。传递自定义 Windows 运行时错误类型就可以了。

这里有几个选项。我们对具有 well-defined、预期故障模式的 Windows 运行时 API 的一般 API 指导是,故障信息应该是正常参数和 return 值的一部分.在这种情况下,我们通常会创建一个 TryDoSomething API 并通过 return 或 out 参数提供扩展的错误信息。这对我们来说效果最好,因为没有一致的方法来跨所有语言映射异常。这是我们希望在未来 xlang 中再次讨论的主题。

HRESULT 可以使用,但需要注意。 HRESULT 值在除 C++ 之外的任何东西中都可能是一个麻烦,在 C++ 中您需要在本地重新定义它们,因为您不能只使用 header。它们会在大多数语言中生成异常,因此如果这很常见,您将为组件的客户端创建调试器噪音。

最后一个选项允许您将存储在 COM object 中的 language-specific 异常传输到 ABI 边界(并向上传输 COM 逻辑堆栈,包括跨编组调用)。实际上,它只能由使用与组件本身相同的编译器、设置和类型定义编译的 C++ 代码使用。例如。将它从使用 VC 编译的组件传递到使用 Clang 编译的组件可能会导致内存损坏。

假设我没有吓跑你,你会想看看 RoOriginateLanguageException。它允许您将异常包装在 COM object 中,并将其与其他 winrt 错误数据一起存储在 TLS 中。我们在投影中使用它来使回调中抛出的异常能够以受控方式使用相同的投影传播到外部代码,这种方式可以通过可能使用其他语言或工具编写的其他代码安全展开。 C#等语言的支持是这样实现的

谢谢,