Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
После инициализации библиотеки COM поток может безопасно использовать COM-интерфейсы. Чтобы использовать com-интерфейс, программа сначала создает экземпляр объекта, реализующего этот интерфейс.
Как правило, существует два способа создания COM-объекта:
- Модуль, реализующий объект, может предоставить функцию, специально разработанную для создания экземпляров этого объекта.
- Кроме того, COM предоставляет универсальную функцию создания с именем CoCreateInstance.
Например, примите гипотетический объект Shape из раздела что такое COM-интерфейс?. В этом примере объект Shape реализует интерфейс с именем IDrawable. Графическая библиотека, реализующая объект Shape, может экспортировать функцию со следующей сигнатурой.
// Not an actual Windows function.
HRESULT CreateShape(IDrawable** ppShape);
Учитывая эту функцию, можно создать новый объект Shape следующим образом.
IDrawable *pShape;
HRESULT hr = CreateShape(&pShape);
if (SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occurred.
}
Параметр ppShape имеет тип указателя на указатель наIDrawable. Если вы еще не видели этот шаблон, двойная косвенность может показаться запутывающей.
Рассмотрим требования функции CreateShape. Функция должна вернуть указатель IDrawable вызывающему. Но возвращаемое значение функции уже используется для кода ошибки или успешности. Поэтому указатель должен быть возвращен через аргумент функции. Вызывающий объект передает переменную типа IDrawable* функции, а функция перезаписывает эту переменную с помощью нового указателя IDrawable. В C++существует только два способа перезаписи значения параметра функции: передачи по ссылке или передачи по адресу. COM использует последний сквозной адрес. А адрес указателя — указатель на указатель, поэтому тип параметра должен быть IDrawable**.
Ниже приведена схема для визуализации того, что происходит.
Функция CreateShape использует адрес pShape (&pShape) для записи нового значения указателя в pShape.
CoCreateInstance: универсальный способ создания объектов
ФункцияcoCreateInstanceпредоставляет универсальный механизм для создания объектов. Чтобы понять, CoCreateInstance, помните, что два COM-объекта могут реализовать один и тот же интерфейс, а один объект может реализовать два или более интерфейсов. Таким образом, универсальная функция, которая создает объекты, нуждается в двух фрагментах информации.
- Какой объект нужно создать.
- Какой интерфейс следует получить из объекта.
Но как мы указываем эту информацию при вызове функции? В COM объект или интерфейс определяется путем назначения 128-разрядного номера, называемого глобально уникальным идентификатором (GUID). Идентификаторы GUID создаются таким образом, чтобы они эффективно были уникальными. Идентификаторы GUID — это решение проблемы создания уникальных идентификаторов без центрального центра регистрации. Идентификаторы GUID иногда называются универсальными уникальными идентификаторами (UUID). До появления COM они использовались в DCE/RPC (распределенной вычислительной среде и удаленном вызове процедур). Существует несколько алгоритмов для создания новых идентификаторов GUID. Не все эти алгоритмы строго гарантируют уникальность, но вероятность случайного создания одного и того же значения GUID дважды крайне мала — фактически ноль. Идентификаторы GUID можно использовать для идентификации любой сущности, а не только объектов и интерфейсов. Однако это единственное использование, которое касается нас в этом модуле.
Например, библиотека Shapes может объявить две константы GUID:
extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable;
(Можно предположить, что фактические 128-разрядные числовые значения для этих констант определены в другом месте.) Константная CLSID_Shape определяет объект Shape, а константная IID_IDrawable определяет интерфейс IDrawable. Префикс CLSID обозначает идентификатор класса , а префикс IID обозначает идентификатор интерфейса. В COM это стандартные соглашения об именовании.
Учитывая эти значения, вы создадите новый экземпляр Shape следующим образом:
IDrawable *pShape;
hr = CoCreateInstance(CLSID_Shape, NULL, CLSCTX_INPROC_SERVER, IID_IDrawable,
reinterpret_cast<void**>(&pShape));
if (SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occurred.
}
Функция CoCreateInstance имеет пять параметров. Первые и четвертые параметры — это идентификатор класса и идентификатор интерфейса. В действительности эти параметры сообщают функции следующее: "Создай объект Shape и предоставь мне указатель на интерфейс IDrawable".
Присвойте второму параметру значение NULL. (Дополнительные сведения о значении этого параметра см. в разделе агрегирование в документации COM.) Третий параметр принимает набор флагов, основной целью которых является указание контекста выполнения для объекта. Контекст выполнения указывает, выполняется ли объект в том же процессе, что и приложение; в другом процессе на одном компьютере; или на удаленном компьютере. В следующей таблице показаны наиболее распространенные значения этого параметра.
| Флаг | Описание |
|---|---|
| CLSCTX_INPROC_SERVER | Тот же процесс. |
| CLSCTX_LOCAL_SERVER | Другой процесс, один и тот же компьютер. |
| CLSCTX_REMOTE_SERVER | Другой компьютер. |
| CLSCTX_ALL | Используйте наиболее эффективный вариант, поддерживаемый объектом. Ранжирование, от наиболее эффективного до наименее эффективного, является следующим: внутрипроцессный, внепроцессный и межкомпьютерный. |
Документация по конкретному компоненту может сообщить вам, какой контекст выполнения поддерживает объект. В противном случае используйте CLSCTX_ALL. Если вы запрашиваете контекст выполнения, который объект не поддерживает, функция CoCreateInstance возвращает код ошибки REGDB_E_CLASSNOTREG. Этот код ошибки также может указывать, что CLSID не соответствует любому компоненту, зарегистрированному на компьютере пользователя.
Пятый параметр в CoCreateInstance получает указатель на интерфейс. Так как CoCreateInstance является универсальным механизмом, этот параметр не может быть строго типизирован. Вместо этого тип данных — void**, и вызывающий должен привести указатель к типу void**. Это цель reinterpret_cast в предыдущем примере.
Важно проверить возвращаемое значение CoCreateInstance. Если функция возвращает код ошибки, указатель интерфейса COM оказывается недопустимым, и попытка разыменовать его может вызвать сбой программы.
Внутри функции CoCreateInstance используются различные методы для создания объекта. В самом простом случае он ищет идентификатор класса в реестре. Запись реестра указывает на библиотеку DLL или EXE, реализующую объект. CoCreateInstance также может использовать сведения из каталога COM+ или параллельного манифеста (SxS). Тем не менее, детали остаются прозрачными для звонящего. Дополнительные сведения о работе CoCreateInstanceсм. в разделе COM-клиенты и серверы.
Пример Shapes, который мы использовали, несколько искусственный, поэтому теперь давайте, например, повернем к реальному примеру COM в действии: отображение диалогового окна Открыть, чтобы пользователь мог выбрать файл.
Следующий
пример : диалоговое окно "Открыть"