Сущность технологии СОМ. Библиотека программиста | страница 100



// for aggregation – для агрегирования

[in] DWORD dwClsCtx,

// locality? – размещение?

[in] REFIID riid,

// what kind of interface – какой вид интерфейса

[out, iid_is(riid)] void **ppv);

// where to put itf – куда разместить интерфейс


Предыдущий пример становится намного проще, если применить CoCreateInstance


HRESULT CreateChimpAndEatBanana(void)

{

IАре *рАре = 0;

HRESULT hr = CoCreateInstance( CLSID_Chimp,

// make a new chimp – создаем нового шимпанзе

0,

// по aggregation – без агрегирования

CLSCTX_ALL,

// any locality – любое расположение

IID_IApe,

// what kind of itf – какой вид интерфейса

(void**)&pApe);

// where to put iff – куда поместить интерфейс

if (SUCCEEDED(hr)) {

assert(pApe);

// use the new object используем новый объект

hr = pApe->EatBanana();

// release the interface pointer

// освобождаем указатель интерфейса

pApe->Release();

}

return hr;

}


Оба предыдущих примера функционально эквивалентны. В сущности, реализация CoCreateInstance просто осуществляет внутренний вызов CoCreateInstanceEx:


// pseudo-code for implementation of CoCreateInstance API

// псевдокод для реализации API-функции

CoCreateInstance HRESULT

CoCreateInstance(REFCLSID rclsid, IUnknown *pUnkOuter, DWORD dwCtsCtx, REFIID riid, void **ppv)

{

MULTI_QI rgmqi[] = { &riid, 0, 0 };

HRESULT hr = CoCreateInstanceEx(rclsid, pUnkOuter, dwClsCtx, 0, 1, rgmqi);

*ppv = rgmqi[0].pItf;

return hr;

}


Хотя возможно выполнить запрос на удаленную активацию с использованием CoCreateInstance, отсутствие параметра COSERVERINFO не позволяет вызывающему объекту задать явное имя хоста. Вместо этого вызов CoCreateInstance и задание только флага CLSCTX_REMOTE_SERVER предписывает SCM использовать конфигурационную информацию каждого CLSID для выбора хост-машины, которая будет использоваться для активации объекта.



Рисунок 3.4 показывает, как параметры CoCreateInstanceEx преобразуются в параметры CoGetClassObject и IClassFactory::CreateInstance. Вопреки распространенному заблуждению, CoCreateInstanceEx не осуществляет внутренний вызов CoGetClassObject. Хотя между двумя этими методиками нет логических различий, реализация CoCreateInstanceEx будет более эффективной при создании одного экземпляра, так как в этом случае не будет лишних вызовов клиент-сервер, которые могли бы понадобиться, если бы была использована CoGetClassObject. Если, однако, будет создаваться большое число экземпляров, то клиент может кэшировать указатель объекта класса и просто вызвать