«Если отладка - процесс удаления ошибок, то программирование должно быть процессом их внесения»
45. Составляющие приложений COM
При разработке приложений, использующих технологию COM, используются структурные элементы, приведенные в таблице.
Элемент |
Назначение |
COM Interface |
Средство, с помощью которого объект COM предоставляет свои функциональные возможности (службы) для внешних клиентов. Объект COM снабжает интерфейсом каждый набор методов и свойств. Любой объект COM имеет один или более интерфейсов |
COM server |
Некоторый модуль (EXE, DLL или OCX), который содержит код для объекта COM |
COM client |
Программный код, который получает требуемые услуги от сервера через интерфейс(ы) объекта COM. Клиент знает, что он хочет получить от сервера, но не знает как его запрос выполняется внутри сервера. В большинстве случаев клиент реализуется как Automation controller (то же, что и ActiveX-клиент) |
Type Library |
Библиотека типов, которая содержит описание COM объекта, его интерфейсов и методов, а также их GUID идентификаторы. Информация из библиотеки записывается в системный реестр и используется клиентским приложением. Delphi предоставляет специальный редактор библиотеки типов, а содержимое библиотеки типов представляет в виде обычного модуля на языке Object Pascal |
Class Factory |
Фабрика классов, экземпляр объекта которой создает COM объект. Сам объект фабрики классов создается COM сервером при запросе клиентским приложением первого интерфейса |
Интерфейсы COM. Клиент взаимодействует с объектом COM посредством интерфейса, который представляет собой набор функционально или семантически связанных подпрограмм, с помощью которых обеспечивается связь клиента с провайдером сервисов (сервером). Стандартный способ изображения интерфейса приведен на рис.1.
Интерфейс |
Объект COM |
Например, каждый COM объект имеет базовый интерфейс IUnknown, который сообщает, какие интерфейсы объекта доступны клиенту. Любой интерфейс сообщает клиенту, какие возможности он предоставляет.
Ключевыми аспектами интерфейсов объектов COM являются следующие:
Ø будучи однажды опубликованным, интерфейс не должен изменяться ни при каких обстоятельствах. При необходимости расширение функциональности должно быть выполнено за счет добавления других интерфейсов;
Ø по соглашению, имя интерфейса должен начинаться с заглавной буквы I, например, IMalloc или IPersist;
Ø интерфейс имеет гарантированный уникальный идентификатор GUID (Globally Unique Identifier), который представляет собой 128-битное случайное число. Эти идентификаторы называют Interface Identifiers (IIDs). Использование таких идентификаторов ограничивает возможность конфликтов между разными версиями или продуктами;
Ø интерфейсы обладают языковой независимостью. Для реализации интерфейса может быть использован любой язык программирования, который поддерживает указатели и структуры и позволяет вызвать функцию по указателю на нее;
Ø сами по себе интерфейсы не являются объектами, а предоставляют способ получения доступ к объекту, а клиент получает доступ к данным объекта посредством вызова функций;
Ø любой интерфейс является наследником базового интерфейса IUnknown;
Ø обращения к интерфейсам могут перенаправляться между потоками, процессами и сетевыми компьютерами невидимо для клиента.
Базовый интерфейс IUnknown. Этот интерфейс, который должны поддерживать все COM объекты, включает следующие подпрограммы:
Ø QueryInterface;
Ø AddRef;
Ø Release.
Метод QueryInterface, объявленный как
Function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
возвращает клиенту указатель на запрошенный интерфейс IID. С помощью полученного указателя клиент может вызвать любой из реализованных методов интерфейса. В качестве IID клиент может указать тип класса интерфейс – в этом случае компилятор самостоятельно извлекает соответствующий GUID.
Методы AddRef и Release используются для того, чтобы объект COM мог самостоятельно отслеживать продолжительность своего существования. Эти методы просто изменяют число ссылок на объект. Когда число ссылок на объект становится равным нулю, объект удаляется из памяти COM сервером.
Указатели на интерфейсы COM объекта. Указатель на интерфейс является 32-битным указателем, который ссылается на указатель на таблицу vtable (см. рис.). Эта таблица является массивом указателей, каждый из которых, в свою очередь, указывает на реализацию метода. Таблица vtable является общей для всех экземпляров объекта, но для каждого из экземпляров создается свой набор данных.
Указатель на интерфейс |
Указатель на vtable |
Указатель на метод 1 |
Указатель на метод 2 |
Указатель на метод 3 |
Код функций интерфейса |
COM серверы. Сервер COM является приложением или библиотекой, которая предоставляет сервис клиентскому приложению (или библиотеке). Сервер включает по крайней мере один объект COM, который в свою очередь представляет собой совокупность методов и свойств. Клиент не обязан знать, где в памяти располагаются объекты COM.
Когда клиент запрашивает сервис у объекта COM, он (клиент) должен передать идентификатор класса CLSID (class identifier). Идентификатор класса CLSID создается на основе GUID интерфейса объекта COM.
По идентификатору класса CLSID COM определяет соответствующий сервер, загружает его в память и сервер создает экземпляр объекта COM. Экземпляры объектов COM создает фабрика классов (class factory), к которой обращается сервер. Фабрика классов имеет свой интерфейс IClassFactory.
Фабрика классов и класс CoClass. COM объект является экземпляром класса CoClass, в котором реализованы один или более интерфейсов COM. Объект COM обеспечивает те сервисы, которые определены в интерфейсах класса CoClass.
Экземпляры класса CoClass создаются специальным типом объекта, который называется фабрикой класса. Когда клиент обращается к COM объекту, фабрика класса создает экземпляр объекта и регистрирует экземпляр объекта для этого конкретного клиента. Если в это время другой клиент обращается к объекту, фабрика классов для него также создает (другой) экземпляр объекта.
Любой класс CoClass должен иметь фабрику классов и идентификатор класса CLSID, так что экземпляр COM объекта этого класса может быть создан извне, т.е. из другого модуля. Благодаря наличию у классов CoClass уникального идентификатора CLSID, они могут быть обновлены в любое время, как только для класса разработан новый интерфейс. Новый интерфейс может использовать модифицированные или новые методы и это не оказывает никакого влияния на прежние версии. В случае использования обычных библиотек DLL подобная ситуация прежде была типичной проблемой.
Мастера Delphi избавляют программиста от необходимости заниматься созданием объектов, которые обеспечивают функционирование фабрики классов.
«44. Введение в COM технологии»
46. Последовательность событий при обращении клиента к серверу COM