Сущность технологии СОМ. Библиотека программиста | страница 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. Если, однако, будет создаваться большое число экземпляров, то клиент может кэшировать указатель объекта класса и просто вызвать