Чтение онлайн

на главную - закладки

Жанры

Сущность технологии СОМ. Библиотека программиста
Шрифт:

Предполагая, что объект класса экспортирует интерфейс IClassFactory вместо IApeClass, клиенты должны использовать метод IClassFactory::CreateInstance для создания новых экземпляров:

HRESULT CreateAGorillaAndEatBanana

{

IClassFactory *pcf = 0;

// find the class object находим объект класса

HRESULT hr = CoGetClassObject(CLSIDGorilla, CLSCTXALL, 0, IIDIClassFactory, (void **)&pcf);

if (SUCCEEDED(hr))

{

IApe *pApe = 0;

// use the class object to create a gorilla

// используем объект класса для создания gorilla

hr = pcf->CreateInstance(0, IIDIApe, (void**)&pApe);

// we're done with the class object, so release it

//

мы закончили с объектом класса, поэтому освобождаем его

pcf->Release;

if (SUCCEEDED(hr))

{

// tell the new gorilla to eat a banana

// приказываем новой горилле есть банан

hr = pApe->EatBanana;

pApe->Release;

}

}

return hr;

}

Этот код является семантически идентичным варианту с функцией, которая использовала интерфейс IApeClass вместо интерфейса IClassFactory.

Для того чтобы предыдущий пример работал корректно, объекту класса Gorilla следует реализовать

IClassFactory : class GorillaClass : public IClassFactory

{

public:

IMPLEMENTUNKNOWNNODELETE(GorillaClass)

BEGININTERFACETABLE(GorillaClass)

IMPLEMENTSINTERFACE(IClassFactory)

ENDINTERFACETABLE

STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)

{

*ppv = 0;

if (pUnkOuter != 0)

// we don't support aggregation yet

// мы еще не поддерживаем агрегирование

return CLASSENOAGGREGATION;

// create a new instance of our C++ class Gorilla

// создаем новый экземпляр нашего С++-класса Gorilla

Gorilla *p = new Gorilla;

if (p == 0) return EOUTOFMEMORY:

// increment reference count by one

// увеличиваем счетчик ссылок на единицу

p->AddRef;

// store the resultant interface pointer into *ppv

// записываем результирующий указатель интерфейса в *ppv

HRESULT hr = p->QueryInterface(riid, ppv);

// decrement reference count by one, which will delete the

// object if QI fails

// уменьшаем на единицу счетчик ссылок,

// что уничтожит объект при отказе QI

p->Release;

// return result of Gorilla::QueryInterface

// возвращаем результат работы Gorilla::QueryInterface

return hr;

STDMETHODIMP LockServer(BOOL bLock);

};

Реализация LockServer будет обсуждаться в этой главе позже. Отметим, что реализация CreateInstance, в первую очередь, создает новый объект C++ на базе класса Gorilla и запрашивает объект, поддерживает ли он нужный интерфейс. Если объект поддерживает требуемый интерфейс, то вызов QueryInterface инициирует вызов AddRef, и клиент в конечном счете выполнит соответствующий вызов Release. Если же произойдет отказ QueryInterface, то потребуется некоторый механизм для уничтожения созданного нового объекта. Предыдущий пример использует стандартную технологию «заключения в скобки» (bracketing) вызова QueryInterface между парой AddRef/Release. Если произошел сбой вызова QueryInterface, то вызов Release сбросит счетчик ссылок на нуль, запуская тем самым удаление объекта. Если же вызов QueryInterface прошел успешно, то вызов Release установит счетчик ссылок на единицу. Остающаяся ссылка принадлежит клиенту, который и выполнит последний вызов Release, когда объект более не нужен.

Оптимизации

Одно

из преимуществ использования стандартного интерфейса для создания экземпляров (instantiation ) состоит в том, что СОМ может обеспечить более эффективную технологию реализации. Рассмотрим следующий код, который создает новый экземпляр класса Chimp:

HRESULT CreateChimp(/* [out] */ IApe * &rpApe)

{

extern const CLSID CLSID_Chimp;

rpApe = 0;

IClassFactory *pcf = 0;

HRESULT hr = CoGetClassObject(CLSID_Chimp, CLSCTX_ALL, 0, IID_IClassFactory, (void**)&pcf);

if (SUCCEEDED(hr))

{

hr = pcf->CreateInstance(0, IID_IApe, (void**)&rpApe);

pcf->Release;

}

return hr;

}

Этот код выполняет одну операцию: создание объекта Chimp. Заметим, что для выполнения одной операции понадобилось три вызова подопераций (suboperations) – CoGetClassObject, CreateInstance, Release. Если сервер загружен как внутрипроцессный, то эти три подоперации не обойдутся слишком дорого. Если, однако, сервер является внепроцессным или внехостовым, то каждая из этих подопераций потребует вызова между процессами клиента и сервера. Хотя СОМ использует очень эффективную передачу IPC/RPC (Interprocess Communication/Remote Procedure Call), каждая из этих подопераций потребует немалых исполнительных затрат. В идеале было бы лучше потребовать, чтобы СОМ перешел на серверный процесс один раз и, находясь там, использовал объект класса для вызова CreateInstance от имени клиента. Если объект класса используется только для реализации IClassFactory, то этот способ будет более эффективным, чем трехшаговый способ, показанный ранее. В СОМ имеется API-функция: CoCreateInstanceEx, относящаяся по своему назначению к той же категории, что CoGetClassObject и IClassFactory::CreateInstance – обеспечивающая создание новых объектов за одно обращение между процессами.

CoCreateInstanceEx дает клиенту возможность задать CLSID для определения, какой объект следует реализовать. В случае успешного выполнения СоСгеаteInstanceEx возвращает один или более указателей интерфейса, которые ссылаются на новый экземпляр заданного класса. При использовании CoCreateInstanceEx клиент никогда не видит промежуточный объект класса, который используется для создания экземпляра объекта. Чтобы клиенты могли вызывать CoCreateInstanceEx, никаких дополнительных функций серверу реализовывать не нужно. С точки зрения сервера все, что необходимо, – это объявить свои объекты классов, как требуется для CoGetClassObject. Реализация CoCreateInstanceEx для нахождения соответствующего объекта класса будет использовать ту же технологию, что и CoGetClassObject. Основное различие заключается в том, что после нахождения объекта CoCreateInstanceEx выполняет дополнительный вызов IClassFactory::CreateInstance, за которым могут последовать один или более вызовов QueryInterface, и все это во время выполнения процесса объекта класса. Можно получить значительную экономию на этапе выполнения, если запрос на активацию закрепить за определенным процессом.

Подобно CoGetClassObject, CoCreateInstanceEx позволяет клиенту задавать желаемые параметры CLSCTX и COSERVERINFO. Кроме того, CoCreateInstanceEx дает клиенту возможность запрашивать более одного указателя интерфейса на вновь создаваемый объект. Это делается путем предоставления клиенту возможности передавать массив структур MULTI_QI, который будет использован для вызова QueryInterface, новому экземпляру во время выполнения серверного процесса:

Поделиться:
Популярные книги

Чайлдфри

Тоцка Тала
Любовные романы:
современные любовные романы
6.51
рейтинг книги
Чайлдфри

Девочка для Генерала. Книга первая

Кистяева Марина
1. Любовь сильных мира сего
Любовные романы:
остросюжетные любовные романы
эро литература
4.67
рейтинг книги
Девочка для Генерала. Книга первая

Все ведьмы – стервы, или Ректору больше (не) наливать

Цвик Катерина Александровна
1. Все ведьмы - стервы
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все ведьмы – стервы, или Ректору больше (не) наливать

Локки 5. Потомок бога

Решетов Евгений Валерьевич
5. Локки
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Локки 5. Потомок бога

В семье не без подвоха

Жукова Юлия Борисовна
3. Замуж с осложнениями
Фантастика:
социально-философская фантастика
космическая фантастика
юмористическое фэнтези
9.36
рейтинг книги
В семье не без подвоха

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Медиум

Злобин Михаил
1. О чем молчат могилы
Фантастика:
фэнтези
7.90
рейтинг книги
Медиум

Пятничная я. Умереть, чтобы жить

Это Хорошо
Фантастика:
детективная фантастика
6.25
рейтинг книги
Пятничная я. Умереть, чтобы жить

Идеальный мир для Лекаря 8

Сапфир Олег
8. Лекарь
Фантастика:
юмористическое фэнтези
аниме
7.00
рейтинг книги
Идеальный мир для Лекаря 8

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Эволюционер из трущоб

Панарин Антон
1. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб

Архил...? Книга 2

Кожевников Павел
2. Архил...?
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Архил...? Книга 2

Бастард Императора. Том 12

Орлов Андрей Юрьевич
12. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 12

Девушка без репутации

Усова Василиса
1. Месть попаданки
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Девушка без репутации