- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Сущность технологии СОМ. Библиотека программиста - Дональд Бокс
Шрифт:
Интервал:
Закладка:
// which interface is desired?
// какой интерфейс требуется?
const IID *piid;
// null on input, will contain the pointer on output
// на входе нуль, на выходе будет содержать указатель
[iid_is(piid)] IUnknown *pItf;
// will contain the HRESULT from QueryInterface on output
// на выходе будет содержать HRESULT от QueryInterface
HRESULT hr;
}
MULTI_QI;
Так как клиент может запрашивать более чем один указатель интерфейса на новый объект, он более не нуждается в явном вызове QueryInterface, если ему требуется более чем один тип указателей интерфейса. Поскольку эти вызовы QueryInterface будут сделаны СОМ от имени клиента по время выполнения внутри процесса объекта класса, более не потребуется никаких обменов данными между клиентом и объектом. Отметим, что каждый из указателей интерфейса, возвращенных CoCreateInstanceEx , будет указывать на один и тот же объект. СОМ не поддерживает внутреннего режима создания нескольких экземпляров за одно обращение.
После постижения структуры MULTI_QI понять определение CoCreateInstanceEx уже нетрудно:
HRESULT CoCreateInstanceEx( [in] REFCLSID rclsid,
// what kind of object? – какого сорта объект?
[in] IUnknown *pUnkOuter,
// for aggregation – для агрегирования
[in] DWORD dwClsCtx,
// locality? – размещение?
[in] COSERVERINFO *pcsi,
// host/security info – информация о хосте/безопасности
[in] ULONG cmqi,
// how many interfaces? – сколько интерфейсов?
[out, size_is (cmqi)] MULTI_QI *prgmq
// where to put itfs – куда разместить интерфейсы );
Если все запрошенные интерфейсы доступны в новом объекте, то CoCreateInstanceEx возвращает S_OK. Если хотя бы один (но не все) из запрошенных интерфейсов недоступен, то CoCreateInstanceEx возвратит CO_S_NOTALLINTERFACES, индицируя частичный успех. Затем вызывающий объект должен исследовать индивидуальные HRESULT в каждой структуре MULTI_QI, чтобы определить, какие интерфейсы были доступны, а какие – нет. Если CoCreateInstanceEx не может создать объект или ни один из запрошенных интерфейсов не доступен, то CoCreateInstanceEx возвращает HRESULT с кодом серьезности ошибки SEVERITY_ERROR, который сообщит, почему произошел отказ в операции.
CoCreateInstanceEx чрезвычайно эффективен в случае, когда требуются интерфейсы нескольких типов. Рассмотрим дополнительное определение интерфейса:
[object,uuid(753A8F7C-A7FF-11d0-8C30-0080C73925BA)]
interface IEgghead : IUnknown
{
import «unknwn.idl»;
HRESULT ContemplateNavel(void);
}
Имея такое определение интерфейса, клиент может привязать оба типа указателей к новому шимпанзе за одно обращение:
void CreateChimpEatBananaAndThinkAboutIt(void)
{
// declare and initialize an array of MULTI_QI's
// объявляем и инициализируем массив MULTI_QI
MULTI_QI rgmqi[2] = { { &IID_IApe, 0, 0 }, { &IID_IEgghead, 0, 0 } };
HRESULT hr = CoCreateInstanceEx( CLSID_Chimp,
// make a new chimp – создаем нового шимпанзе
0,
// no aggregation – без агрегирования
CLSCTX_ALL,
// any locality – размещение любое
0,
// no explicit host/security info
// нет явной информации о хосте и безопасности
2,
// asking for two interfaces – запрашиваем 2 интерфейса
rgmqi);
// array of MULTI_QI structs – массив структур
MULTI_QI
if (SUCCEEDED(hr)) {
// hr may be CO_S_NOTALLINTERFACES, so check each result
// hresult может быть равен CO_S_NOTALLINTERFACES,
// поэтому проверяем каждый результат
if (hr == S_OK || SUCCEEDED(rgmqi[0].hr)) {
// it is safe to blindly cast the resultant ptr to the type
// that corresponds to the IID used to request the interface
// безопасно вслепую преобразовать результирующий
// указатель к типу, соответствующему тому IID,
// который использовался при запросе интерфейса
IАре *рАре = reinterpret_cast<IApe*>(rgmqi[0].pItf);
assert(pApe);
HRESULT hr2 = pApe->EatBanana();
assert(SUCCEEDED(hr2));
pApe->Release();
}
if(hr == S_OK || SUCCEEDED(rgmqi[1].hr)) {
IEgghead *peh = reinterpret_cast<IEgghead*>(rgmqi[1].pItf);
assert(peh);
HRESULT hr2 = peh->ContemplateNavel();
assert(SUCCEEDED(hr2));
peh->Release();
}
} }
Рисунок 3.3 показывает шаги, которые предпринимаются CoCreateInstanceEx для создания нового объекта. Важно отметить, что оба результирующих указателя будут указывать на один и тот же объект. Если нужны два различных объекта, то требуются и два отдельных вызова CoCreateInstanceEx.
Использование СоСrеateInstanceЕх достаточно просто, если нужен только один интерфейс:
HRESULT CreateChimpAndEatBanana(void)
{
// declare and Initialize a MULTI_QI
// определяем и инициализируем MULTI_QI
MULTI_QI mqi = { &IID_IApe, 0, 0 };
HRESULT hr = CoCreateInstanceEx( CLSID_Chimp,
// make a new chimp – создаем нового шимпанзе
0,
// по aggregation – без агрегирования CLSCTX_ALL,
// any locality – любое расположение
0,
// no explicit host/security Info
// нет явной информации о хосте/безопасности
1,
// asking for one interface – запрашиваем один интерфейс
&mqi);
// array of MULTI_QI structs – массив структур
MULTI_QI
if (SUCCEEDED(hr))
{
IApe *pApe = reinterpret_cast<IApe*>(mqi.pItf);
assert(pApe);
// use the new object – используем новый объект
hr = pApe->EatBanana();
// release the Interface pointer
// освобождаем указатель интерфейса
pApe->Release();
}
return hr;
}
Если нужен только один интерфейс и не передается COSERVERINFO, то СОМ предусматривает несколько более удобную версию CoCreateInstanceEx, именуемую CoCreateInstance[1]:
HRESULT CoCreateInstance( [in] REFCLSID rclsid,
// what kind of object? – какой тип объекта?
[in] IUnknown *pUnkOuter,
// 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. Если, однако, будет создаваться большое число экземпляров, то клиент может кэшировать указатель объекта класса и просто вызвать IClassFactory::CreateInstance несколько раз. Поскольку IClassFactory::CreateInstance является всего лишь вызовом метода и не идет через SCM, он отчасти быстрее, чем вызов CoCreateInstanceEx. Порог, за которым становится более эффективным кэшировать объект класса и обходить CoCreateInstanceEx, будет изменяться в зависимости от эффективности IPC и RPC на используемых хост-машинах и сети.
Снова интерфейс и реализация
В предыдущих примерах активации со стороны клиента осуществлялись явные вызовы API-функций СОМ для активации. Часто может понадобиться много шагов для корректной связи с требуемым объектом (например, создать один тип объекта, затем запросить его для ссылки на другой объект, основанный на некоторой информации в запросе). Чтобы избавить клиентов от заботы об алгоритмах по поиску объектов или их созданию, СОМ поддерживает стандартный механизм назначения произвольных имен объектам, на которые они ссылаются. Этот механизм основан на использовании локаторных объектов (locator objects), которые инкапсулируют свой алгоритм связи, скрывая его за стандартным постоянным интерфейсом. Эти локаторы объектов формально называются моникерами и являются просто СОМ-объектами, экспортирующими интерфейс IMoniker. Интерфейс IMoniker является одним из наиболее сложных интерфейсов СОМ; тем не менее, он объявляет один метод, чрезвычайно важный для данной дискуссии, а именно BindToObject: