Сохраняет ли ABI больше информации об ошибках, чем HRESULT? - PullRequest
0 голосов
/ 25 апреля 2019

При переносе обычного класса C ++ в класс среды выполнения Windows я столкнулся с довольно серьезным препятствием.Мой класс C ++ сообщает об определенных условиях ошибки, выбрасывая пользовательские объекты ошибок.Это позволяет клиентам удобно фильтровать исключения, задокументированные в общедоступном интерфейсе.

Кажется, я не могу найти надежный способ передачи достаточного количества информации через ABI для репликации той же точности 1 с использованиемСреда выполнения Windows.Исходя из предположения, что HRESULT является единственной обобщенной информацией об ошибках, я оценил следующие параметры:

  1. «Очевидный» выбор: сопоставить условие исключения с любым из предопределенных Значения HRESULT .Хотя это технически работает (предположительно), на сайте вызовов нет возможности различить ошибки, возникающие из реализации, и ошибки, возникающие из вызываемых реализацией.
  2. Изобретайте пользовательские HRESULT s.Если этот макет все еще применяется к среде выполнения Windows, я мог бы легко установить бит Customer и сойти с ума с моим 27-битным представлением кода ошибки.Это работает, пока кто-то другой не сделает то же самое.Я не знаю ни одного способа приписать HRESULT интерфейсу, который бы разрешил эту неоднозначность.
  3. Даже если любое из вышеперечисленного можно заставить работать как положено, выдает hresult_error s, как предписано, сайт вызова все еще будет зависеть от языковой проекции.Хотя C #, по-видимому, позволяет передавать любой System.Exception (- производный) объект ошибки через ABI и перебрасывать их на сайт вызова, C ++ / WinRT поддерживает только 14 различных типов исключений (см. throw_hresult ).

Поскольку ни одна из этих опций не позволяет достаточно полную информацию об ошибках для пересечения ABI, кажется, что HRESULT просто может быть недостаточно.Есть ли в среде выполнения Windows какие-либо средства, позволяющие дополнительной (произвольной) информации об ошибках пересекать ABI?


1 Я не очень заинтересован в передаче фактического C ++исключения по всему.Вместо этого я ищу способ, позволяющий клиентам уникально идентифицировать документированные условия ошибок естественным образом.Передача пользовательских типов ошибок Windows Runtime будет в порядке.

1 Ответ

1 голос
/ 26 апреля 2019

Здесь есть несколько вариантов.Наше общее руководство по API для API среды выполнения Windows, которые имеют четко определенные ожидаемые режимы сбоев, заключается в том, что информация об ошибках должна быть частью обычных параметров и возвращаемого значения.В этой ситуации мы обычно создаем API TryDoSomething и предоставляем расширенную информацию об ошибках с помощью параметра return или out.Это работает лучше всего для нас, потому что нет единого способа сопоставления исключений для всех языков.Это тема, которую мы надеемся еще раз обсудить в xlang в будущем.

HRESULT можно использовать с оговоркой.Значения HRESULT могут создавать неудобства во всем, кроме C ++, где вам нужно переопределить их локально, потому что вы не можете просто использовать заголовок.Они будут генерировать исключения в большинстве языков, поэтому, если это распространено, вы будете создавать шум отладчика для клиентов ваших компонентов.

Последняя опция позволяет вам передавать исключение для конкретного языка, хранящееся в COM-объекте.через границу ABI (и до логического стека COM, в том числе через маршаллированные вызовы).На практике он будет использоваться только кодом C ++, скомпилированным с тем же компилятором, настройками и определениями типов, что и сам компонент.Например, передача его из компонента, скомпилированного с помощью VC, в компонент, скомпилированный с помощью Clang, может привести к повреждению памяти.

Предполагая, что я вас не напугал, вы захотите взглянуть на RoOriginateLanguageException .Это позволяет вам обернуть исключение в COM-объект и сохранить его вместе с другими данными об ошибках winrt в TLS.Мы используем это в проекциях, чтобы позволить исключениям, генерируемым в обратном вызове, распространяться на внешний код, используя ту же проекцию контролируемым образом, который безопасно перематывается через другой код, потенциально написанный с использованием других языков или инструментов.Вот как реализована поддержка в C # и других языках.

Спасибо,

Бен

...