Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
СТАТЬЯ
Введение в COM
Часть 1
Автор: michael dunn
Перевод: Илья Простакишин
Источник: The Code Project
Предмет данной статьиЯ написал это руководство для программистов, которые начинают осваивать COM и нуждаются в помощи для понимания основ этой концепции. Статья содержит краткое введение в спецификацию COM, объясняет основные термины и описывает примеры использования существующих компонентов COM. Прошу обратить внимание, что эта статья не научит вас тому, как писать собственные объекты и интерфейсы.
ВведениеCOM (Component Object Model – Объектно-Компонентная Модель) – одно из трехбуквенных сокращений, которые сегодня очень часто используются в Windows (вспомните – API, MFC, OLE, ATL). Множество новых технологий, разрабатывающихся постоянно, базируется на COM. Документация просто пестрит терминами типа COM object (объект COM), interface (интерфейс), server (сервер), и так далее, но везде почему-то предполагается, что вы уже знакомы с тем, как COM работает и как ее использовать.
Эта статья является вводной для начинающих, она описывает основные используемые механизмы, а также показывает как использовать объекты COM, поставляемые со стороны (особенно, оболочкой Windows). После знакомства со статьей вы сможете использовать COM-объекты, как встроенные в Windows, так и предоставляемые третьими лицами.
Я предполагаю, что вы уже являетесь специалистом в C++. Я частично использую в своих примерах MFC и ATL, и в этих случаях смысл кода будет поясняться, на случай, если вы не знакомы с этими библиотеками. […]
Что такое COM?COM – это метод разделения двоичного кода между разными приложениями, написанными на разных языках программирования. Это не совсем то, что обеспечивает C++, а именно повторное использование исходного кода. ATL – хороший пример такого подхода. Отлаженный исходный код может повторно использоваться и нормально работать только в C++. При этом существует возможность коллизий между именами, не говоря уже о неприятностях при наличии множества копий одинакового кода в ваших проектах.
Windows позволяет разделять код между приложениями с помощью библиотек DLL. Я не раскрою большого секрета, если скажу, что все функции Windows содержатся в различных внешних библиотеках – kernel32.dll, user32.dll и т.д., которые доступны любому Windows – приложению, и более того, должны им использоваться. Но DLL расчитаны на использование только посредством интерфейса С или языков, понимающих стандарты вызова языка C. Таким образом, реализация языка программирования является барьером между создаваемым приложением и уже реализованными процедурами, содержащимися внутри DLL-библиотеки.
В MFC был введен новый механизм разделения двоичного кода – библиотеки расширения MFC (MFC extension DLLs). Но это еще более ограниченный метод, т.к. вы можете использовать его только в приложениях, созданных на основе библиотеки MFC.
COM решает все эти проблемы. Делается это посредством введения двоичного стандарта. При этом спецификация COM требует, чтобы двоичные модули (DLL и EXE) компилировались в соответствие со специфической структурой, которая декларируется этим стандартом. Стандарт также в точности определяет, каким образом COM-объекты должны быть организованы в памяти. Вдобавок, двоичная структура не должна быть зависима от особенностей языка программирования (как, например, стандарта описаний имен в C++). Все это нужно для того, чтобы облегчить доступ к модулю приложения, созданного на любом языке программирования. Двоичный стандарт возлагает "бремя" совместимости на "плечи" компилятора, облегчая задачу вам, как создателю компонентов, и другим людям, которые будут пользоваться вашими компонентами.
Структура расположения COM-объектов в памяти очень похожа на модель, которая используется в C++ виртуальными функциями, поэтому многие компоненты COM создаются с использованием языка C++. Однако, здесь важно заметить, что язык, на котором вы пишите, не имеет значения, поскольку результат можно использовать в будущем с любыми языками программирования.
Строго говоря, COM не является спецификацией, привязанной к Win32. Теоретически, можно портировать ваши COM-объекты в Unix или любые другие ОС. Однако, я никогда не видел, чтобы COM применялась где-то за пределами сферы влияния Microsoft.
Основные определенияНачнем двигаться снизу-вверх. Итак, интерфейс (interface) – это простая группа функций. Эти функции, в свою очередь, называются методами (methods). Имена интерфейсов начинаются с буквы I, например IShellLink. В терминологии C++ интерфейс представляет собой абстрактный базовый класс, содержащий только чистые виртуальные функции (pure virtual functions).
Интерфейсы могут наследоваться (inherit) от других интерфейсов. Наследование работает также, как и одиночное наследование в C++. Множественное наследование для интерфейсов не применяется.
CO-класс (coclass) (сокращение от component object class) содержится в dll или exe и включает код одного или нескольких интерфейсов. Говорят, что CO-класс поддерживает или реализует (implement) эти интерфейсы. Объект COM (COM object) – это экземпляр CO-класса в памяти. Заметьте, что "класс" COM – это не тоже самое, что "класс" C++, хотя часто бывает, что класс COM реализуется посредством класса C++.
Сервер COM (COM server) – это двоичный файл (DLL или EXE), содержащий один или несколько CO-классов.
Регистрация (registration) – это процесс создания записей в реестре, которые сообщают Windows о том, где можно найти определенный сервер COM. Дерегистрация (unregistration) наоборот – удаление этих данных из реестра.
GUID (рифмуется с "fluid" – "жидкий, текучий", сокращение от globally unique identifier – Глобальный Уникальный Идентификатор) – это 128-битный номер, который используется COM для идентификации различных элементов. Каждый интерфейс и CO-класс имеет GUID. Коллизии между именами невозможны, поскольку каждый GUID абсолютно уникален и повторение GUID очень маловероятно (если вы используете для их создания функции COM API). Вы также можете иногда встретить термин UUID (сокращение от universally unique identifier). uuid и guid это практически одно и тоже.
ID класса (class ID) или CLSID – это GUID, которым обозначается CO-класс. В свою очередь, ID интерфейса (interface ID) , или IID – это GUID, обозначающий интерфейс.
Существует две причины, по которым идентификаторы GUID так широко используются в COM:
1. GUID это всего лишь число. Любой язык программирования может оперировать им.
2. Каждый GUID, создаваемый на любой машине, уникален (если создан правильно). Следовательно, два COM-разработчика не могут использовать одни и те же GUID. Это решает проблему по выделению уникальных GUID и устраняет необходимость в специальном центре по выделению GUID (как, например, при регистрации доменов в Internet).
HRESULT – это целочисленный тип, который используется COM для возврата кодов ошибок или кодов завершения. Не смотря на то, что имя типа начинается с префикса H, он (этот тип) не является дескриптором. Переменная типа HRESULT способна участвовать в любых логических операциях языка C, например != и ==.
Наконец, Библиотека COM (COM library) – это часть операционной системы, с которой вы взаимодействуете, когда делаете что-либо с элементами COM. Часто библиотека COM называется просто "COM" и иногда это приводит к некоторой путанице.
Работа с объектами COMКаждый язык реализует операции с объектами по-разному. Например, в C++ вы создаете объекты на стеке, либо с помощью new динамически выделяете для них место в "куче". Поскольку COM должна быть нейтральна к языку, библиотека COM включает свои собственные средства управления объектами. Сравним управление объектами в COM и C++:
Создание нового объекта• В C++ используется оператор new, либо объект создается на стеке.
• В COM вызывается специальная API-функция библиотеки COM.
Удаление объектов• В C++ используется оператор delete, либо объект удаляется автоматически при выходе из области видимости.
• В COM каждый объект хранит свой собственный счетчик обращений. Когда вы заканчиваете работу с объектом, вы должны сообщить ему, что он вам больше не нужен. Когда счетчик обращений равен 0, объект сам выгружается из памяти.
Теперь, между этими двумя стадиями – создания и удаления объекта – вы, естественно, должны использовать этот объект. Когда вы создаете COM-объект, вы сообщаете библиотеке COM, какой интерфейс вам нужен. Если объект был успешно создан, библиотека COM возвращает указатель на запрашиваемый интерфейс. С его помощью вы можете вызывать методы этого интерфейса, также как при использовании обычного объекта C++.