Создание внутрипроцессных серверов автоматизации. Обработка ошибок (общие сведения)

   
На этом шаге мы приведем общие сведения об обработке ошибок.

   
Соглашения о вызовах были рассмотрены на 302 шаге и там же было сказано, что в СОМ-интерфейсах
используют соглашения stdcall и safecall. Однако из приведенной там таблицы 1 нельзя понять разницу между этими
соглашениями - оба они помещают параметры в стек справа налево, и в обоих стек очищает вызываемый метод. Разница между этими
соглашениями заключается в том, что директива safecall не только определяет соглашение о вызовах, но осуществляет обработку
ошибок в СОМ-интерфейсах. Сразу же следует оговориться, что описанная ниже обработка ошибок верна как для внутрипроцессного
сервера автоматизации (DLL), так и для внепроцессного сервера (ЕХЕ), но во внутрипроцессных серверах автоматизации
директива safecall несет еще и информацию о работе со стеком.

   
Базовая модель обработки ошибок СОМ заключается в том, что все методы представляют собой функции, возвращающие значение
типа HRESULT - целое число. При успешном завершении функции она должна вернуть значение S_OK (0), в случае ошибки -
код ошибки. Кроме того, СОМ-сервер может предоставить по запросу клиента дополнительную информацию об ошибке при помощи
методов реализованных им интерфейсов ISupportErrorInfo и IErrorInfo. Такой стиль программирования привычен для
разработчиков на языке C++, однако плохо согласуется с принятой в Delphi моделью обработки ошибок, связанной с исключениями.

   
Именно для устранения этого противоречия в Delphi введен дополнительный тип соглашения о вызовах, задаваемый директивой safecall.
По умолчанию он используется для реализации функций объектов ActiveX и при импорте библиотек типов. Впрочем, это поведение
можно изменить при помощи диалогового окна Environment Options.


Рис.1. Настройка соглашения о вызовах safecall

   
Целевые интерфейсы для соглашения о вызовах safecall выбираются с помощью группы переключателей SafeCall function mapping:

  • All v-table interfaces - соглашение о вызовах safecall поддерживается для всех интерфейсов;
  • Only dual interfaces - соглашение о вызовах safecall поддерживается только для дуальных интерфейсов (реализующих интерфейс IDispatch);
  • Do not map - соглашение о вызовах safecall не поддерживается.

   
Как же тогда осуществляется взаимодействие с серверами и клиентами, созданными не в Delphi? Ведь они не поддерживают соглашения
о вызовах safecall. Правильно. А ответ прост - компилятор Delphi тоже не компилирует такие методы во что-то уникальное.
Они преобразуются в обычные функции, возвращающие значение типа HRESULT и поддерживающие соглашение о вызовах
stdcall, но с некоторыми дополнительными изменениями, которые мы рассмотрим в следующих шагах.

   
На следующем шаге мы рассмотрим соглашение о вызовах safecall на клиенте.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий