Сущность технологии COM


Исключения - часть 4


Довольно просто отобразить исключения СОМ в исключения C++, причем в любом месте. Определим следующий класс, который упаковывает объект исключений СОМ и HRESULT в один класс C++:

struct COMException { HRESULT m_hresult; // hresult to return // hresult для возврата IErrorInfo *m_pei; // exception to throw // исключение для выбрасывания COMException(HRESULT hresult, REFIID riid, const OLECHAR *pszSource, const OLECHAR *pszDesc, const OLECHAR *pszHelpFile = 0, DWORD dwHelpContext = 0) { // create and init an error info object // создаем и инициализируем объект информации об ошибке ICreateErrorInfo *рсеi = 0; HRESULT hr = CreateErrorInfo(&pcei); assert(SUCCEEDED(hr)); hr = pcei->SetGUID(riid); assert(SUCCEEDED(hr)); if (pszSource) hr=pcei->SetSource(const_cast<OLECHAR*>(pszSource)); assert(SUCCEEDED(hr)); if (pszDesc) hr=pcei->SetDescription(const_cast<OLECHAR*>(pszDesc)); assert(SUCCEEDED(hr)); if (pszHelpFile) hr=pcei->SetHelpFile(const_cast<OLECHAR*>(pszHelpFile)); assert(SUCCEEDED(hr)); hr = pcei->SetHelpContext(dwHelpContext); assert(SUCCEEDED(hr)); // hold the HRESULT and IErrorInfo ptr as data members // сохраняем HRESULT и указатель IErrorInfo как элементы данных m_hresult = hresult; hr=pcei->QueryInterface(IID_IErrorInfo, (void**)&m_pei); assert(SUCCEEDED(hr)); pcei->Release(); } };

С использованием только что приведенного С++-класса COMException показанный выше метод Snore может быть модифицирован так, чтобы он преобразовывал любые исключения C++ в исключения СОМ:

STDMETHODIMP PugCat::Snore(void) { HRESULT hrex = S_OK; try { if (this->IsAsleep()) return this->DoSnore(); else throw COMException(PUG_E_PUGNOTASLEEP, IID_IPug, OLESTR("PugCat"), OLESTR("I am not asleep!")); } catch (COMException& ce) { // a C++ COMException was thrown // было сброшено исключение COMException C++ HRESULT hr = SetErrorInfo(0, ce.m_pei); assert(SUCCEEDED(hr)); ce.m_pei->Release(); hrex = ce.m_hresult; } catch (...) { // some unidentified C++ exception was thrown // было выброшено какое-то неидентифицированное исключение C++ COMException ex(E_FAIL, IID_IPug, OLESTR("PugCat"), OLESTR("A C++ exception was thrown")); HRESULT hr = SetErrorInfo(0, ex.m_pei); assert(SUCCEEDED(hr)); ex.m_pei->Release(); hrex = ex.m_hresult; } return hrex; }

Заметим, что реализация метода заботится о том, чтобы не позволить чисто С++-исключениям переходить через границы метода. Таково безусловное требование СОМ.

1

Спецификация СОМ использует термин логический поток (logical thread) для наименования последовательности вызовов методов, которая может превосходить физический OS-поток.

2

Объект, который обеспечивает выполнение GetErrorInfo, декларирует, что он явно программирует с использованием исключений СОМ и что никаких ошибочных исключений, сброшенных объектами младшего уровня, случайно не распространилось.




Начало  Назад  Вперед