HRESULT hr = LoadRegTypeLib(LIBID_PrimeLib, 1, 0, 0, &ptl);

assert(SUCCEEDED(hr));

hr = ptl->GetTypeInfoOfGuid(IID_DIPrimeManager, &m_pTypeInfo);

ptl->Release(); } virtual PrimeManager(void) { m_pTypeInfo->Release(); }

};

Имея приведенное выше определение класса, метод GetTypeInfo просто возвращает описание данного интерфейса:

STDMETHODIMP PrimeManager::GetTypeInfo (UINT it, LCID lcid, ITypeInfo **ppti) {

assert(it == 0 && ppti != 0);

(*ppti = m_pTypeInfo)->AddRef();

return S_OK;

}

Если бы объект поддерживал несколько локализованных библиотек типов, то реализации следовало бы использовать параметр LCID, чтобы решить, какое описание типа нужно возвратить. Соответствующая реализация GetTypeInfoCount еще проще:

STDMETHODIMP PrimeManager::GetTypeInfoCount(UINT *pit) {

assert(pit != 0); *pit = 1;

// only 0 or 1 are allowed

// допускаются только 0 или 1

return S_OK;

}

Единственными допустимыми значениями счетчика являются нуль (это означает, что данный объект не содержит описаний своего интерфейса) и единица (это означает, что данный объект содержит описания своего интерфейса). Даже если объект поддерживает несколько локализованных описаний типа, результирующий счетчик остается равным единице.

Методы GetTypeInfo и GetTypeInfoCount фактически являются вспомогательными. Истинным ядром интерфейса IDispatch являются методы GetIDsOfNames и Invoke. Реализация GetIDsOfNames направляет вызов в машину синтаксического анализа библиотеки типов, встроенную в СОМ:

STDMETHODIMP PrimeManager::GetIDsOfNames(REFIID riid, OLECHAR **pNames, UINT cNames, LCID lcid, DISPID *pdispids) {

assert(riid == IID_NULL);

return m_pTypeInfo->GetIDsOfNames(pNames, cNames, pdispids);

}

Поскольку библиотека типов содержит все имена методов и соответствующие им DISPID , реализация не представляет труда для синтаксического анализатора. Метод Invoke реализован аналогичным образом:

STDMETHODIMP PrimeManager::Invoke(DISPID id, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pd, VARIANT *pVarResult, EXCEPINFO *pe, UINT *pu) {

assert(riid == IID_NULL);

void *pvThis = static_cast<DIPrimeManager*>(this);

return m_pTypeInfo->Invoke(pvThis, id, wFlags, pd, pVarResult, pe, pu);

}

Первым параметром ITypeInfo::Invoke является указатель на интерфейс. Тип этого интерфейса должен быть таким же, как интерфейс, который описан в информации о типах. Когда передаваемые аргументы корректно синтаксически преобразованы в стек вызова (call stack), синтаксический анализатор будет вызывать текущие методы через этот интерфейсный указатель. Рис. 7.6 иллюстрирует последовательность вызовов для сред подготовки сценариев, которые осуществляют вызовы через двойственные интерфейсы.

Двунаправленные интерфейсные контракты

Как было показано в главе 5, объекты, постоянно находящиеся в различных апартаментах, могут использовать сервисные программы друг друга вне зависимости от того, резидентом какого апартамента является другой объект. Поскольку удаленный доступ в СОМ основан на концепции апартаментов, разработчикам необходимо рассматривать процессы не как клиенты или серверы в чистом виде, а скорее как набор из одного или нескольких апартаментов, которые способны одновременно экспортировать и импортировать интерфейсы.

Как два объекта договариваются о том, чьи интерфейсы будут использоваться для взаимного сотрудничества, в значительной степени является спецификой области применения. Для примера рассмотрим следующий интерфейс, моделирующий программиста:

[uuid(75DA6457-DD0F-11d0-8C58-0080C73925BA),object]

interface IProgrammer : IUnknown {

HRESULT StartHacking(void);

HRESULT IsProductDone([out, retval] BOOL *pbIsDone);

}

Клиент будет использовать такой интерфейс следующим образом:

HRESULT ShipSoftware(void)

{

IProgrammer *pp = 0;

HRESULT hr = CoGetObject(OLESTR(«programmer:Bob»), 0,

IID_IProgrammer, (void**)&pp);

if (SUCCEEDED(hr)) {

hr = pp->StartHacking();

BOOL bIsDone = FALSE;

while (!bIsDone && SUCCEEDED(hr)) {

Sleep(15000);

// wait 15 seconds

// ожидаем 15 секунд

hr = pp->IsProductDone(&bIsDone);

// check status

// проверяем состояние

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату