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

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

Жанры

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

Предполагая, что объект класса экспортирует интерфейс 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, новому экземпляру во время выполнения серверного процесса:

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

Доктора вызывали? или Трудовые будни попаданки

Марей Соня
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Доктора вызывали? или Трудовые будни попаданки

Последняя Арена 11

Греков Сергей
11. Последняя Арена
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Последняя Арена 11

Ученик. Книга третья

Первухин Андрей Евгеньевич
3. Ученик
Фантастика:
фэнтези
7.64
рейтинг книги
Ученик. Книга третья

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

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

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Барон Дубов

Карелин Сергей Витальевич
1. Его Дубейшество
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Барон Дубов

Сумеречный стрелок 6

Карелин Сергей Витальевич
6. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный стрелок 6

Мастер 8

Чащин Валерий
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мастер 8

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Кодекс Охотника. Книга VII

Винокуров Юрий
7. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
4.75
рейтинг книги
Кодекс Охотника. Книга VII

Демон Системы. Часть 2

Poul ezh
4. Пехотинец Системы
Фантастика:
попаданцы
фэнтези
фантастика: прочее
5.00
рейтинг книги
Демон Системы. Часть 2

Дорога к счастью

Меллер Юлия Викторовна
Любовные романы:
любовно-фантастические романы
6.11
рейтинг книги
Дорога к счастью

Возвышение Меркурия. Книга 14

Кронос Александр
14. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 14

Я – Легенда

Гарцевич Евгений Александрович
1. Я - Легенда!
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Я – Легенда