С помощью чего реализуется технология сом

Использование технологии COM

Технология СОМ реализуется с помощью СОМ-библиотек (в число которых входят такие файлы операционной системы, как OLE32.DLL и OLE-Aut32.DLL). СОМ-библиотеки содержат набор стандартных интерфейсов, которые обеспечивают функциональность СОМ-объекта, а также небольшой набор функций API, отвечающих за создание и управление СОМ-объектов.

Клиенты не знают, как СОМ-объект выполняет свои действия. СОМ-объект предоставляет свои услуги при помощи интерфейсов. В дополнение, приложению-клиенту не нужно знать, где находится СОМ-объект. Технология СОМ обеспечивает прозрачный доступ независимо от местонахождения СОМ-объекта.

В общих чертах, СОМ-сервер должен выполнять следующие действия :

— регистрировать данные в системном реестре Windows для связывания модуля сервера с идентификатором класса (CLSID);

— предоставлять фабрику СОМ-класса, создающую экземпляры СОМ-объектов;

— обеспечивать механизм, который выгружает из памяти серверы СОМ, которые в текущий момент времени не предоставляют услуг клиентам.

Достоинствами технологии СОМ является то, что, во-первых, создание СОМ-объектов не зависит от языка программирования. Таким образом, СОМ-объекты могут быть написаны на различных языках. Во вторых, СОМ-объекты могут быть использованы в любой среде программирования под Windows. В число этих сред входят Delphi, Visual C++, C++Builder, Visual Basic, и многие другие. Эти достоинства позволяют легко обеспечить интеграцию самых разнообразных приложений в рамках СОМ-технологии.

Компоненты СОМ состоят из исполняемого кода, распространяемого в виде динамически компонуемых библиотек (DLL) или ЕХЕ-файлов Win32. Один такой файл может содержать как одиночный СОМ-объект, так и несколько СОМ-объектов. Компоненты, написанные в соответствии со стандартом СОМ, удовлетворяют всем требованиям компонентной архитектуры.

C точки зрения разработчика, возможны два класса задач, связанных с использованием технологии COM:

· создание собственных COM-объектов;

· применение уже имеющихся COM-объектов.

Первый класс задач более сложен и требует от разработчика достаточно глубокого знакомства с технологией COM и ее компонентами. В рамках данной работы мы не будем рассматривать эти задачи. Задачи же второго класса значительно проще, ибо применение уже имеющихся COM-объектов, по сути, мало чем отличается от работы с обычными объектами. Поскольку в состав самой Windows входят многочисленные COM-объекты, а многие приложения имеют хорошо документированные соответствующие иерархии COM-объектов (объектные модели), то создание таких приложений обычно не представляет особых трудностей.

В процессе выполнения заданий по второй учебной практике вы познакомились с двумя технологиями, базирующимися на технологии COM –OLE Automation, широко применяющейся в рамках пакета Microsoft Office, и технологиейActiveX, представляющих собой общее название ряда близких технологий фирмы Microsoft, таких как ActiveX-Controls, ActiveX-Documents и ActiveScripting. технологияActiveXпредназначена, в первую очередь, для работы в распределенных компьютерных системах (локальные и глобальные сети). Однако она может быть использована и для интеграции приложений и на локальных компьютерах, так как позволяет создавать и использовать программные компоненты, предоставляющие различные сервисы другим приложениям и операционной системе.

Для выполнения базовых функций и использования интерфейсов, в ОС Windows существует специальная библиотека COM. Набор ее функций можно рассматривать как подмножество функций Windows API, поэтому к ним всегда возможен доступ стандартным способом – вызовом соответствующих функций. Согласно спецификации СОМ, имена всех функций этой библиотеки начинаются с приставки “Co” (например, CoCreateInstance, CoGetClassObject и т. п.).

С помощью этой библиотеки можно осуществлять запуск серверов объектов.

С помощью чего реализуется технология сом. Смотреть фото С помощью чего реализуется технология сом. Смотреть картинку С помощью чего реализуется технология сом. Картинка про С помощью чего реализуется технология сом. Фото С помощью чего реализуется технология сом
На рис. 2.6 показан процесс создания первого экземпляра объекта с помощью библиотеки COM и системного реестра. Допустим, что клиент пытается обратиться к объекту COM, который до этого момента не использовался. Следовательно, клиент не имеет указателя на нужный объект и интерфейс. Для получения этих данных, ему необходимо обратиться к библиотеке COM для вызова (1) специального метода CoCreateInstance, передавая ему в качестве параметра CLSID нужного класса (CLSID_2), IID интерфейса (IID2_A) и требуемый тип сервера. Здесь (и далее) числовой номер в скобках соответствует номеру в последовательности выполнения операций, который на рис. 2.6 указывается в кружках на стрелках.

В общих чертах, СОМ-сервер должен выполнять следующие действия:

— регистрировать данные в системном реестре Windows для связывания модуля сервера с идентификатором класса (CLSID);

— предоставлять фабрику СОМ-класса, создающую экземпляры СОМ-объектов;

— обеспечивать механизм, который выгружает из памяти серверы СОМ, которые в текущий момент времени не предоставляют услуг клиентам.

Согласно спецификации СОМ фабрика класса также является объектом СОМ. Объект СОМ имеет право называться фабрикой класса, если он поддерживает интерфейс iclassFactory. В нем реализованы всего два метода:

CoCreatelnstance— создает новый экземпляр класса. Все необходимые параметры, кроме iid, метод получает от фабрики класса. В этом его отличие от одноименной общей функции Windows API;

LockServer— оставляет сервер функционировать после создания объекта.

Для вызова фабрики класса существует специальная функция библиотеки классовcoGetclassObject:

С помощью чего реализуется технология сом. Смотреть фото С помощью чего реализуется технология сом. Смотреть картинку С помощью чего реализуется технология сом. Картинка про С помощью чего реализуется технология сом. Фото С помощью чего реализуется технология сом

В качестве параметра ей передается clsid нужного класса и iid интерфейса (iclassFactory). Функция ищет требуемую фабрику и возвращает указатель на интерфейс. С его помощью, используя методCoCreatelnstance, клиент заставляет фабрику класса создать объект.

Расширения COM

Технология СОМ изначально разрабатывалась как ядро для осуществления межпрограммного взаимодействия. Уже на этапе разработки предполагалось расширять возможности технологии при помощи так называемых расширений СОМ. СОМ расширяет собственную функциональность, благодаря созданию специализированных наборов интерфейсов для решения конкретных задач.

Примером могут служить ранее упоминавшиеся технология автоматизации (automation) и технология ActiveX. Однако, на этом список возможных расширений СОМ далеко не исчерпывается. Постоянно идет доработка старых и создание новых, более совершенных технологий межпрограммного взаимодействия. В табл. 2.1 представлены некоторые из наиболее часто используемых в настоящее время (но далеко не все!) расширений СОМ.

В табл. 2.2 приведены основные особенности объектов для каждого из вышеприведенных расширений СОМ.

Если не считать простейшего COM-объекта (COM-сервера), содержащего один базовый интерфейс Iunknown и, один или несколько пользовательских интерфейсов, то наиболее простым из указанных в таблице 2.1 расширений СОМ является сервер автоматизации. По сути, он представляет собой простейший COM-сервер, дополненный еще одним интерфейсом – Idispatch.

Технология автоматизации (OLE Automation)разработана на основе технологии СОМ. Так же как и СОМ, автоматизация позволяет использовать функции одних приложений в других приложениях.Автоматизация— это механизм обмена информацией между процессами в операционной системе Windows, с помощью которого одна прикладная программа может управлять другой. Технология OLE Automation обеспечивает выполнение базовых функций, позволяющих обособленным программным модулям связываться и обмениваться информацией. Многие используемые в технологии автоматизации термины подобны тем, которые применяются при описании технологии СОМ.

Объект автоматизации не имеет принципиальных отличий от объекта СОМ и представляет собой отдельный, самодостаточный объект, разработанный для выполнения специфической задачи или функции. Отличие от объекта СОМ заключается только в том, что доступ к объектам автоматизации осуществляется через специальные интерфейсы, называемые интерфейсамидиспетчеризации(dispinterface). Интерфейсы диспетчеризации похожи на обычные интерфейсы СОМ, но позволяют упростить обращение к объекту автоматизации. Приложение, предоставляющее те или иные сервисы и применяющее для этой цели интерфейсы содержащихся внутри него адресного пространства COM-объектов, называется сервером автоматизации. Приложение, использующее эти сервисы, называется контроллером автоматизации и может быть создано с помощью подавляющего большинства современных средств разработки программного обеспечения.

Сервер автоматизациипредставляет собой исполняемый модуль, который может включать в себя несколько объектов автоматизации.

Контроллером (диспетчером) автоматизациипринято называть клиентское приложение, управляющее объектом автоматизации. Контроллер автоматизации для управления объектом автоматизации использует методы интерфейсов этого объекта. Для получения информации об интерфейсах служат библиотеки типов.

Обычно, в состав современных сред разработки включаются т. н.мастера (Wizards) для создания разнообразных объектов СОМ. Они позволяют создавать СОМ-объекты при помощи мастера, а также регистрировать и тестировать созданные объекты.

Мастера СОМ-объектов выполняют следующие действия:

Источник

Основы технологии COM

Примечание
Хотя технология СОМ обладает явными плюсами, она имеет также и минусы, среди которых зависимость от платформы. То есть, данная технология применима только в операционной системе Windows и на платформе Intel.

С помощью чего реализуется технология сом. Смотреть фото С помощью чего реализуется технология сом. Смотреть картинку С помощью чего реализуется технология сом. Картинка про С помощью чего реализуется технология сом. Фото С помощью чего реализуется технология сом
Рис. 3.1. СОМ-интерфейс

Примечание
По правилам обозначения СОМ-объектов, интерфейсы СОМ-объекта обозначаются кружками справа или слева от СОМ-объекта. Базовый интерфейс lUnknown рисуется кружком сверху от СОМ-объекта.

Для примера, каждый СОМ-объект всегда поддерживает основной СОМ-интерфейс lUnknown, который применяется для передачи клиенту сведений о поддерживаемых интерфейсах.
Как уже говорилось выше, СОМ-объект может иметь несколько интерфейсов, каждый из которых обеспечивает какую-либо свою функцию.
Ключевыми аспектами СОМ-интерфейсов являются следующие.
— Однажды определенные, интерфейсы не могут быть изменены. Таким образом, вы можете возложить на один интерфейс определенный набор функций. Дополнительную функциональность можно реализовать с помощью дополнительных интерфейсов.
— По взаимному соглашению, все имена интерфейсов начинаются с буквы I, например IPersist, IMalloc.
— Каждый интерфейс гарантированно имеет свой уникальный идентификатор, который называется глобальный уникальный идентификатор (Globally Unique Identifier, GUID). Уникальные идентификаторы интерфейсов называют идентификаторами интерфейсов (Interface Identifiers, IIDs). Данные идентификаторы обеспечивают устранение конфликтов имен различных версий приложения или разных приложений.
— Интерфейсы не зависят от языка программирования. Вы можете воспользоваться любым языком программирования для реализации СОМ-интерфейса. Язык программирования должен поддерживать структуру указателей, а также иметь возможность вызова функции при помощи указателя явно или неявно.
— Интерфейсы не являются самостоятельными объектами, они лишь обеспечивают доступ к объектам. Таким образом, клиенты не могут напрямую обращаться к данным, доступ осуществляется при помощи указателей интерфейсов.
— Все интерфейсы всегда являются потомками базового интерфейса Iunknown.
Основной СОМ-интерфейс IUnknown
Базовый интерфейс lunknown достаточно подробно был рассмотрен во второй главе книги. В дополнение ко всему вышесказанному, добавим, что интерфейс lunknown обеспечивает механизм учета ссылок (счетчик ссылок на СОМ-объект). При передаче указателя на интерфейс выполняется метод интерфейса lunknown AddRef. По завершении работы с интерфейсом приложение-клиент вызывает метод Release, который уменьшает счетчик ссылок.
При вызове метода Querylnterface интерфейса Iunknown в метод передается параметр IID, имеющий тип TGUID, т. е. идентификатор интерфейса. Параметр метода out возвращает либо ссылку на запрашиваемый интерфейс, либо значение NH. Результатом вызова метода может быть одно из значений, перечисленных в табл. 3.1.
Таблица 3.1. Значения, возвращаемые методом Queryinterface

Интерфейс не поддерживается

Примечание
Для создания СОМ-объектов и СОМ-серверов Delphi предоставляет мастера, который значительно упрощает процедуру. Об этом читайте следующую главу.

Серверы автоматизации (Automation servers)

Источник

Способы реализации СОМ серверов

При работе с объектами COM клиент не знает, где находится объект. Он просто обращается к объекту посредством его интерфейса. Далее библиотека COM выполняет все необходимые шаги для удовлетворения вызова клиента.

Эти шаги зависят от конкретного местонахождения объекта COM: в том же процессе, что и клиент, в другом процессе на машине клиента или на другой машине в сети. В зависимости от этого различают три вида серверов COM.

Сервер в клиентском процессе (In-process server)

Это библиотека DLL, которая выполняется в адресном пространстве процесса клиента. Например, элемент ActiveX, внедренный в Web страницу, выполняется в Internet Explorer или другом браузере. Это значит, что объект ActiveX загружается на машину клиента и выполняется в том же процессе, что и Web браузер. Клиент обращается к объекту COM путем прямого вызова интерфейса COM.

Рисунок 3. Сервер в клиентском процессе

Локальный сервер (local server)

Он представляет собой другое приложение (файл *.exe), которое выполняется в другом адресном пространстве, но на том же компьютере, что и клиентское приложение. Например, обработка таблицы Excel, внедренной в документ Word, выполняется приложением Excel. Локальный сервер связывается с клиентом посредством COM библиотек.

Рисунок 4. Локальный сервер

Когда объект COM принадлежит другому процессу на том же компьютере, что и клиентское приложение, или вовсе на другом компьютере (в сети), COM использует так называемого «заместителя» (proxy) для того, чтобы инициировать удаленный вызов процедуры (remote procedure call – RPC). Так как заместитель находится в клиентском процессе, то с точки зрения клиента обращения к интерфейсам выглядят так же, как и для случая размещения сервера в клиентском процессе. Заместитель перехватывает вызовы клиента и отправляет их туда, где находится сервер. Механизм, который позволяет клиенту получить доступ к объекту, находящемуся в другом процессе или на другом компьютере (невидимо для клиента), называется маршалингом или маршализацией.

Удаленный сервер (remote server)

Он представляет собой библиотеку (DLL или OCX) или другое приложение, которые выполняются на другом компьютере, а не на машине клиента. Например, клиентское приложение, использующее базу данных, связывается с приложением, выполняемым на другом компьютере в сети. В этом случае удаленный сервер использует интерфейсы DCOM.

Рисунок 5. Удаленный сервер

Различие между локальным и удаленным сервером состоит в применяемом способе (и инструментальных средствах) взаимодействия клиента и сервера: в первом случае используется COM, а во втором – DCOM.

Если сервер реализован как библиотека (а библиотека не может выполняться как самостоятельное приложение), то COM создает специальное приложение-суррогат (surrogate), в рамках которого и выполняется библиотека.

Маршалинг

Механизм маршалинга позволяет клиентскому приложению делать вызовы методов интерфейса для объекта COM, который находится в другом процессе или на другом компьютере.

При любом вызове функций посредством интерфейса клиентское приложение помещает фактические параметры функции в стек и выполняет ее вызов. Если функция не находится в клиентском процессе, то вызов передается заместителю. Заместитель упаковывает параметры в пакет и передает их удаленному объекту. Заглушка COM объекта распаковывает пакет, помещает аргументы в стек и вызывает объект COM. Таким образом объект COM обрабатывает запрос клиента в своем собственном адресном пространстве.

Какой именно маршалинг будет реализован, зависит от реализации COM объекта. Стандартный механизм реализован интерфейсом IDispatch. Кроме того, объекты могут самостоятельно выполнять маршалинг, однако это довольно сложно.

Отметим, что технология Microsoft Transaction Server (MTS) обеспечивает дополнительную поддержку для удаленных объектов.

Последовательность создания простого COM объекта в Delphi

В данном разделе рассматривается алгоритм разработки простого COM объекта, реализованного в виде библиотеки DLL, подключаемой к приложению.

Процесс создания COM объекта состоит из следующих этапов:

Проектирование COM объекта

На этом этапе необходимо выбрать вид используемого интерфейса. Мастер предлагает использование в качестве базового (родительского) любого из нескольких интерфейсов. В данном разделе будет предполагаться выбор предлагаемого по умолчанию интерфейса IUnknown.

Далее необходимо определиться с типом сервера. Для всех типов серверов, кроме удаленных, COM выполняет маршалинг автоматически и без использования библиотеки типов, но для удаленных серверов надо использовать библиотеку типов или самостоятельно выполнять маршалинг. Использование библиотеки типов существенно облегчает разработку СОМ объекта, предоставляя «паскалевский» доступ к методам СОМ объекта

Этап 1. Выполнить тему меню File\New\ActiveX\ActiveX Library, с помощью которой будет создана заготовка проекта, включающего сервер. На этом этапе потребуется только сохранить проект под заданным именем, в данном примере SimpleCOM. В результате будет создан файл проекта (единственный, без модулей) с таким содержимым.

library SimpleCOM;
uses ComServ;
exports
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;

Этап 2. Выполнить тему меню File\New\ActiveX\COM Object для добавления в проект объекта COM. В результате появится диалоговое окно, в котором необходимо задать параметры нового объекта.

Теперь необходимо заполнить поля ввода предлагаемой мастером формы.

Окно COM Object WizardНазначение
ClassNameИмя разрабатываемого объекта COM.
InstancingСпособ создания экземпляра объекта (instancing mode). Возможные значения: internal, single instance и multiplay instance. Если COM объект используется только внутри процесса, значение этого поля игнорируется.
Threading modelМодель поточной обработки, указывающая на то, как клиентское приложение может обращаться к интерфейсу COM объекта. Эта модель также влияет на то, как объект будет регистрироваться, и на детали его реализации.
Implemented interfacesИмя интерфейса – это имя класса с предшествующим символом I. Генерируется мастером автоматически.
DescriptionСтрока описания класса, используемая при его регистрации.
Include Type LibraryУстановка этого режима приводит к включению в проект библиотеки типов – генерации нового интерфейса для класса CoClass. При отключении этого режима этот интерфейс надо разрабатывать самостоятельно.
Mark interface OLEAutomationПодключение маршалинга, главным образом для внутрипроцессных серверов. Этот режим может быть включен только при включенном режиме подключения библиотеки типов.

При создании простого СОМ объекта можно оставить все установки, предлагаемые мастером, без изменения, за исключением имени объекта. При выборе имени объекта необходимо учесть, что Delphi автоматически добавит в имя первый символ «Т».

После задания требуемых значений и нажатия кнопки OK появится следующее диалоговое окно редактора библиотеки типов:

Еще до каких-либо установок в этом окне в проект будет добавлен новый модуль, который мы сохраним под именем Main. Исходный код этого модуля следующий:

Кроме того, будет сгенерирован и добавлен в проект файл с именем SimpleCOM_TLB.pas, который обеспечивает наиболее удобный и простой доступ к интерфейсам и методам СОМ объекта. Наибольший интерес представляют следующие фрагменты кода этого файла:

class function Create: ISmpCOM;

class function CreateRemote(const MachineName: string): ISmpCOM;

Теперь вернемся к диалоговому окну редактора библиотеки типов. Повторный вызов редактора библиотеки типов можно выполнить с помощью команды F12 (Toggle Form/Unit) при активном окне с текстом файла SimpleCOM_TLB.pas. С помощью этого редактора удобнее всего снабдить наш СОМ объект дополнительными (кроме уже имеющегося ISmpCOM) интерфейсами и собственно методами, которые будут реализовать функциональность нашего объекта.

Этап 3. Для добавления новых (функциональных) методов к имеющемуся интерфейсу ISmpCOM требуется выполнить такие действия:

В иерархическом списке в левом окне редактора выбрать интерфейс ISmpCOM и щелкнуть на кнопке New Method в панели инструментов.

Заменить стандартное имя метода Method1 на требуемое, например, Tangent. На странице Parameters необходимо задать тип возвращаемого методом значения, а также имена и типы параметров. На остальных страницах можно все оставить без изменений.

Проделываем ту же последовательность действий для другого метода ­– Cube.

Щелкаем на кнопке Refresh Implementation для модификации исходных текстов файлов Main.pas и SimpleCOM_TLB.pas.

Файл Main.pas теперь стал таким:

Если посмотреть на содержимое файла SimpleCOM_TLB.pas, то в нем можно заметить такие изменения:

function Tangent(Angle: Double): Double; stdcall;

function Cube(Arg: Double): Double; stdcall;

Эти же методы добавлены и в описание класса TSmpCOM = class(TOleServer).

Этап 4. Добавляем необходимый код в методы Tangent и Cube.

Этап 5. Подобным образом добавляем еще один интерфейс ISmpCOM2 и метод Summa, затем модифицируем исходный код метода Summa. На странице Attributes в окне Parent interface необходимо выбрать IUnknown.

Этап 6. Вновь разработанный интерфейс требуется «привязать» к объекту SmpCOM. Для этого необходимо в левом окне редактора выбрать объект SmpCOM, а в правой части окна редактора – страницу Implements. Щелкаем на списке имеющихся интерфейсов правой кнопкой мыши и выбираем интерфейс ISmpCOM2.

Этап 7. Вновь щелкнем на кнопке Refresh Implementation для модификации исходных текстов файлов Main.pas и SimpleCOM_TLB.pas. Редактируем текст функции Summa. Содержимое файла Main.pas теперь станет таким:

Этап 8. Регистрация COM объекта.

Последнее, что осталось сделать – это откомпилировать проект и зарегистрировать его в качестве сервера с помощью команды Run\Register ActiveX Server. При этом регистрируется также и библиотека типов, содержимое которой можно просмотреть с помощью OLE View. Альтернативный способ – использование команды tregsvr (MS DOS) или выполнение программы regsvr32.exe Windows.

Тестирование COM объекта. Этот этап зависит от функциональности объекта и состоит в проверке работоспособности методов объекта.

Использование OLE View для получения информации о сервере. После регистрации СОМ сервера информацию о нем можно просмотреть с помощью OLE View. В разделе Object classes/All Objects информация о сервере будет записана под именем, заданным в окне редактора библиотеки типов Help String для сокласса. Таким образом, строка Help String выступает в качестве внешнего имени сокласса (СОМ сервера). В разделе Type Libraries можно найти информацию о библиотеке типов под именем, которое было указано в окне Help String редактора библиотеки типов для библиотеки типов.

Разработка и использование локального сервера

Выше был рассмотрен алгоритм реализации внутрипроцессного сервера (in-proc server), который представляет собой библиотеку DLL, загружаемую в адресное пространство клиентского приложения. В этом разделе рассматривается разработка локального сервера (local server), который реализуется как самостоятельное приложение – exe-файл. Локальный сервер может быть также реализован и как DLL-библиотека, но в этом случае для него требуется использовать в качестве «носителя» специальное приложение, называемое суррогатом (surrogate). Суррогаты обеспечиваются технологией DCOM и СОМ+.

В данном разделе будет рассмотрен способ реализации сервера в качестве «обычного» приложения, разрабатываемого с помощью Delphi.

Разработка сервера

Этап 1. Создать типовое приложение, сохранить файл проекта под требуемым именем.

Этап 2. Добавить к проекту библиотеку типов с помощью меню File\New\ActiveX\Type Library. Библиотека типов будет автоматически включена в проект (в предложение uses файла проекта). Подключение полученного *_TLB.pas файла к другим модулям проекта надо выполнить вручную.

Этап 3. Добавить к проекту СОМ объект с помощью меню File\New\ActiveX\COM Object. Delphi создаст новый модуль-заготовку для СОМ объекта (сервера) и подключит его к проекту. Можно было бы пропустить этап 2, так как при включении в приложение нового СОМ объекта, использующего библиотеку типов, файл библиотеки (*_TLB.pas) добавляется в проект автоматически.

Этап 4. Как и для случая внутрипроцессного сервера, далее требуется добавить в СОМ объект необходимые интерфейсы и методы для них с помощью редактора библиотеки типов и добавить необходимый код в функциональные методы СОМ объекта.

Этап 5. Откомпилировать проект и запустить на выполнение. При первом же запуске сервер и библиотека будут автоматически зарегистрированы в реестре Windows.

Сервер можно также зарегистрировать, запустив его на выполнение с параметром /RegServer командной строки:

Сервер при этом на выполнение не запускается. Разрегистрация сервера выполняется так:

Разработка клиентского приложения

Приложение-клиент строится так же, как и для случая использования внутрипроцессного сервера. При запуске клиентского приложения на выполнение и вызове метода Create сокласса автоматически загружается приложение-носитель запрашиваемого СОМ объекта и выполняются методы, запрашиваемые клиентским приложением.

Сервер будет оставаться в памяти до тех пор, пока клиентское приложение будет иметь ссылку на СОМ объект. Например, если интерфейс (в клиентском приложении) описать как глобальную переменную, то сервер будет оставаться в памяти до тех пор, пока эта переменная будет существовать, т.е. до окончания работы клиентского приложения. Если ссылка на интерфейс будет описана как локальная переменная в какой-либо подпрограмме, то сервер будет выгружен из памяти при завершении работы этой подпрограммы. При попытке закрытия приложения сервера в тот момент, когда клиентское приложение имеет ссылку на СОМ объект, будет выдано предупреждение (заголовок окна – COM Server Warning) о том, что сервер используется другим приложением.

При запуске на выполнение нескольких экземпляров клиентских приложений приложение-сервер будет запущено только в одном экземпляре, если при включении СОМ объекта в проект были оставлены значения его свойств, предлагаемые по умолчанию.

Запуск сервера сопровождается появлением главного окна приложения. Это окно можно скрыть, если, например, в обработчике события OnPaint вызвать метод Hide для того, чтобы скрыть главное окно приложения. В этом случае при запуске приложения-сервера на выполнение (обычным образом или из клиентского приложения) главное окно приложения появляться не будет. Такое решение не очень подходит, так как при автономном запуске локального сервера его главное окно должно появляться. Выход – анализ командной строки на предмет наличия ключа /Embedding или –Embedding. Например, можно добавить в приложение такой обработчик события OnPaint:

По всей видимости, лучший выход – это перехват сообщения об открытии или прорисовке окна или перекрытие соответствующего метода главной формы приложения.

Интерфейсы

Интерфейс IUnknown поддерживает три метода и таблица виртуальных методов VTBL для объекта, поддерживающего этот интерфейс, должна иметь такой вид:

IUnknown.QueryInterface
IUnknown.AddRef
IUnknown.Release

Когда разработчик объекта добавляет свой интерфейс IMyInterface, предоставляющий методы и свойства некоторого объекта, таблица VTBL приобретает такой вид:

IUnknown.QueryInterface
IUnknown.AddRef
IUnknown.Release
IMyInterface.Method1
IMyInterface.Method2
другие методы и свойства IMyInterface

Для объекта, поддерживающего интерфейсы IUnknown и IDispatch, та же таблица приобретает вид:

IUnknown.QueryInterface
IUnknown.AddRef
IUnknown.Release
IDispatch.GetIDsOfNames
IDispatch.GetTypeInfo
IDispatch.GetTypeInfoCount
IDispatch.Invoke

Отметим, что объекты, имеющие диспетчерский интерфейс, не могут не иметь интерфейса IUnknown.

Интерфейс IDispatch, в отличие от IUnknown, предоставляет возможность позднего связывания, что необходимо при программировании на интерпретируемых языках. IDispatch не имеет индивидуальных методов для доступа к методам и свойствам объекта автоматизации. Вместо этого он предоставляет единственный метод Invoke, предназначенный для доступа к свойствам COM объекта и вызова его методов.

Для вызова конкретного метода объекта необходимо, сначала, получить номер метода с помощью функции GetIDsOfNames, а затем полученный номер метода указать в вызове функции Invoke. Функция GetIDsOfNames имеет такой заголовок:

Function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;

Вызывающая программа должна передать через указатель Names имя (или имена) требуемого метода, а номер (или номера) метода получает через указатель DispIDs. Возвращаемое функцией значение описано в табл.

Возвращаемое значение

Описание
S_OKОшибки нет
E_OUTOFMEMORYНедостаточно памяти
DISP_E_UNKNOWNNAMEОдно или более имен неизвестны. Возвращаемый массив идентификаторов DISPIDs содержит значение DISPID_UNKNOWN для каждого неизвестного имени
DISP_E_UNKNOWNLCIDНе распознан идентификатор локализации LCID

Главный метод интерфейса IDispatch имеет описан как:

Function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word;
var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;

Номер метода передается через параметр DispID, а фактические параметры вызываемого метода – через Params, который представляет собой указатель на структуру. Не вдаваясь в подробное толкование параметров Invoke отметим только, что формирование списка фактических параметров является сравнительно трудоемким занятием. Этих трудностей можно избежать, так как вызывающая программа на Object Pascal может и не использовать метод Invoke, что будет рассмотрено позже.

Function GetTypeInfoCount(out Count: Integer): HResult; stdcall;

позволяет узнать, доступна ли информация о типах данного COM объекта. Если он возвращает значение Count=1, то информация доступна, а если Count=0 – то нет.

Получить информацию о типах можно с помощью метода

Function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;

который возвращает информацию через указатель на интерфейс библиотеки типов TypeInfo.

Диспинтерфейс (dispinterface) представляет собой объявление методов, доступных через интерфейс IDispatch. Он позволяет упростить использование методов интерфейса IDispatch благодаря тому, что компилятор в этом случае имеет возможность выполнить контроль типов при вызове методов объекта или обращении к его свойствам. При этом, тем не менее, используется позднее связывание. В конечном итоге вызов метода диспинтерфейса Delphi преобразует в вызов метода Invoke с соответствующими параметрами. Из этого следует, что на самом деле, в отличие от раннего связывания, наличие вызываемого метода или свойства у объекта не проверяется и не может быть проверено на этапе компиляции. Вот пример описания диспинтерфейса:

function Summa(X: Integer; Y: Integer): Integer; dispid 1;

Если к объекту, имеющему интерфейс IDispatch, добавить свой собственный интерфейс (custom interface), то мы получим двойственный (дуальный) интерфейс (dual interface) и таблица VTBL в этом случае приобретает такой вид:

IUnknown.QueryInterface
IUnknown.AddRef
IUnknown.Release
IDispatch.GetIDsOfNames
IDispatch.GetTypeInfo
IDispatch.GetTypeInfoCount
IDispatch.Invoke
IMyInterface.Method1
IMyInterface.Method2
другие методы и свойства IMyInterface

Дуальный интерфейс удобен тем, что предоставляет возможность осуществления как раннего, так и позднего связывания методов COM объекта. Для его реализации объявления методов собственного интерфейса (производного от IUnknown) должны быть идентичны объявлениям методов в диспинтерфейсе.

Разработка клиентских приложений для MS Office

Есть три основных способа создания клиентских приложений MS Office:

1. Генерация интерфейсного модуля для сервера путем импорта библиотеки типов

2. Включение в проект требуемого сервера как компонента Delphi, например, WordApplication

3. Использование требуемого приложения MS Office как сервера автоматизации. В этом случае клиентское приложение называют контроллером автоматизации.

В чем разница между этими способами? В первых двух случаях при разработке клиентского приложения используется раннее связывание, что обеспечивает разработчику более комфортные условия, так как корректность вызовов методов сервера проверяется еще на этапе компиляции и, соответственно, облегчается отладка приложения. Достоинством третьего способа является его универсальность и языковая независимость, так как контролер автоматизации может быть реализован практически на любом из ныне распространенных языков программирования.

Рассмотрим эти три способа на простом примере создания нового файла с помощью MS Word и записи в него абзаца, состоящего из одной строки.

Использование MS Word путем импорта библиотеки типов

Создадим обычное приложение, далее с помощью команды Project | Import Type Library вызовем диалог по импорту библиотеки типов. В появившемся диалоговом окне в списке библиотек типов надо выбрать Microsoft Word Object Library и с помощью кнопки Create Unit создать файл с библиотекой типов, приняв предлагаемое по умолчанию имя файла Word_TLB.pas (проект WordAppTlb).

С учетом добавления кнопки текст модуля проекта может выглядить таким образом:

Как видно из текста (единственной) процедуры, основное неудобство состоит в необходимости описания достаточно большого числа переменных типа OleVariant, так как параметры многих методов сервера Word описаны как параметры переменные. Неудобно также то, что справочной информации по методам в Delphi Help нет, а доступны лишь оперативные подсказки по именам и типам параметров.

Использование MS Word путем включения в проект компонента Delphi

Замечание. Как и в случае импорта библиотеки типов, рассмотренном в предыдущем разделе, для MS Office XP описываемый подход не работает. Приведенный ниже пример относится к использованию Delphi 6 и MS Office 2000.

Для реализации этого способа надо создать обычное приложение и добавить в него компонент TWordApplication (страница Servers палитры компонент).

С учетом добавления кнопки текст модуля может выглядить таким образом:

Как видно из текста программы, использование сервера Word посредством включения в проект компонента очень похоже на предыдущий способ. В модуле Word2000.pas тип TWordApplication описан как класс, производный от TOleServer:

Таким образом, от программиста просто скрывается за оболочкой TWordApplication явное получение интерфейса.

Запуск сервера Word производится автоматически в момент запуска приложения, если, конечно, Word в это время не запущен. Закрывать Word надо самостоятельно, например, в методе FormClose. Однако, если Word был запущен не приложением, то метод App.Quit все равно будет пытаться завершить работу Word.

К достоинствам этого способа можно отнести тот факт, что в модуле Word2000.pas определены константы, по именам которых можно догадаться о назначении отдельных параметров методов и значениях свойств.

Разработка клиентских приложений для MS Office как контролеров автоматизации

Клиентское приложение для любой из программ MS Office как контролер автоматизации создается достаточно просто. В качестве примера рассмотрим приложение, которое просто запускает MS Word и прекращает работу с ним. Для разработки такого приложения надо:

Создать обычный проект, добавить на форму две кнопки и подключить к главному модулю проекта модули ComObj и ActiveX.

В требуемом месте запустить копию сервера MS Word или подключиться к уже имеющейся, если таковая есть.

Выполнить необходимые действия с использованием объектов MS Word.

Закрыть приложение MS Word.

Вот пример текста главного модуля проекта Main.pas (проект WordAppAuto):

Как найти информацию по объектам, предоставляемым серверами MS Office?

Во-первых, это документация MSDN, а именно раздел Office Developer Documentation. Конкретные примеры программирования (на языке VBA – Visual Basic for Application) проще всего искать в файлах, соответствующих маске vba*.chm. Например, файл vbawd10.chm содержит справочную информацию по объектам сервера MS Word, а vbaxl9.chm – по MS Excel. Кстати, библиотеку типов серверов приложений MS Office можно импортировать из файлов *.olb. Например, библиотека типов Microsoft Word 2000 находится в файле MSWord9.olb.

Во-вторых, можно использовать такой сервис приложений MS Office, как запись макросов. Например, чтобы воспользоваться этим средством в MS Word, надо проделать такие операции:

Запустить на выполнение MS Word и включить запись макроса – Сервис/Макрос/Начать запись. В появившемся диалоговом окне можно изменить имя макроса и сферу его применения

Выполнить «вручную» те операции, которые необходимо запрограммировать. При этом возможно с помощью кнопок панели управления макроса приостановить или отменить запись

После завершения всех операций остановить запись и открыть текст макроса, например, с помощью команды Сервис/Макрос/Редактор Visual Basic. Сгенерированный текст макроса можно использовать как шаблон для записи текста программы.

Вот пример макроса с именем МойМакрос, сгенерированного при выполнении таких операций: создание нового документа, сохранение его под именем MyDoc.doc, ввод строки текста «Any text» и закрытие документа.

Результат «трансляции» этого макроса на язык Object Pascal выглядит так:

Простые СОМ-клиенты и СОМ-серверы

Для иллюстрации описанных приемов работы с СОМ приведем два примера на языке C++, в которых используется СОМ. Они достаточно просты и используют язык C++ и функции СОМ API. Всю работу будем проделывать самостоятельно, без использования таких структур, как MFC или ATL. Хотя примеры и тривиальны, на них вполне можно продемонстрировать основные приемы, используемые в СОМ. Ниже мы применим новую библиотеку активных шаблонов фирмы Microsoft, чтобы заново реализовать данный пример сервера.

Прежде чем мы начнем разработку, необходимо внести существенное изменение в интерфейс компонента. Первоначальное определение абстрактного класса выглядит следующим образом:

Такой способ объявления порождает одну проблему. Каждый метод СОМ-интерфейса должен возвращать значение типа HRESULT. В нашем случае возвращается только результат операции. Поэтому нам требуется возвратить HRESULT, а результат операции передать через параметр. Это выглядит следующим образом:

Такая запись несколько необычна, поскольку известно, что возврат методом значения вычислений уменьшает сложность программы. Теперь же приходится работать с указателем на возвращаемый результат. Возвращение значения типа HRESULT каждым методом является общим правилом в СОМ. Однако существуют технические приемы (например, ключевое слово языка определения интерфейсов retval), позволяющее приложению клиента трактовать каждый метод таким образом, как если бы он на самом деле возвращал результат, а не HRESULT. Ниже мы рассмотрим эту возможность на примере клиента.

Макросы STDMETHOD и STDMETHODIMP

Результат развертывания макроса зависит от целевой среды и языка программирования: С или C++. Для среды Win32 с использованием C++ определение этого макроса выглядит следующим образом:

Модификатор указывает на необходимость соблюдения определенного соглашения фирмы Microsoft относительно вызовов, используемого в API-функциях Win32. Это соглашение требует, чтобы вызываемая программа очищала стек после своего вызова. Модификатор — всего лишь способ обозначить функцию как чисто виртуальную (pure virtual, т.е. = 0).

Большая часть методов СОМ-интерфейсов возвращает стандартный тип HRESULT. В этом состоит единственное различие между макросами STDMETHOD и STDMETHOD_, поскольку метод, определенный как STDMETHOD, всегда возвращает данные типа HRESULT, а определение макроса STDMETHOD_ позволяет пользователю задавать тип возвращаемого значения. Вот как в определении интерфейса IClassFactory используется макрос STDMETHOD:

Макрос STDMETHOD применен для объявления методов интерфейса, как в абстрактных определениях, так и в определениях класса. Единственным отличием является модификатор PURE. Приведем программу для производного класса:

И, наконец, при реализации класса используется макрос STDMETHODIMP. Приведем пример релизации класса Math:

Приложение сервера обеспечивает реализацию интерфейса IMath и, таким образом, создает и помещает на хранение компонент Math. Его определение встречалось на протяжении всей данной главы, поэтому здесь мы не будем останавливаться на нем подробно. Для разработки примера сервера воспользуемся средой разработки Visual C++. Затем с помощью утилиты AppWizard создадим проект Dynamic Link Library с именем Server. Таким образом, мы получим простой проект Visual C++, не имеющий исходных файлов.

Теперь необходимо объявить интерфейс абстрактного компонента и его CLSID и IID. Наберите следующий текст и сохраните его в файле с именем IMATH.H.

Чтобы предоставить программе клиента информацию об определениях интерфейса и идентификаторов CLSID и IID, необходимо отделить их от собственно текста программы. Только благодаря этому программа клиента может получить доступ к функциям компонента. Фактически клиент не нуждается в CLSID (поскольку доступ к компоненту осуществляется с помощью его ProgID), поэтому ничто не помешает нам расположить его именно здесь.

Строки, начинающиеся с макроса DEFINE_GUID, можно ввести таким же образом, как это сделано здесь, либо создать ваши собственные с помощью утилиты GUIDGEN. Теперь необходимо объявить класс компонента и фабрику классов для него. Чтобы сделать это, создайте файл с именем МАТН.Н и введите следующие определения:

Большая часть этих строк встречалась вам и раньше. Класс Math является производным по отношению к классу интерфейсов IMath, который в свою очередь является производным для IUnknown. Объявим методы IUnknown и IMath. Отслеживание общего количества экземпляров компонента в DLL-файле и количества вызовов IClassFactory::LockServer возлагается на две глобальные переменные. Затем объявляем класс для фабрики классов компонента Math. Теперь можно взглянуть, на текст программы. Создайте файл МАТН.СРР и введите в него следующее:

В конструкторе внутренний счетчик инициализируется значением нуль, а значение счетчика экземпляров для DLL-файла увеличивается. Затем деструктор его уменьшает. Теперь добавьте в программу следующее:

Таким образом, будет обеспечена реализация трех методов интерфейса IUnknown. Наш компонент поддерживает только два интерфейса: обязательный IUnknown и пользовательский IMath. Функция QueryInterface проверяет возможность получения клиентом требуемого интерфейса, а также возвращает указатель на указатель виртуальной таблицы компонента. Перед возвратом указателя увеличивается значение внутреннего счетчика обращений. Это осуществляется с помощью вызова метода AddRef(). Реализации функций AddRef() и Release() ничем не отличаются от использованных ранее.

Мы получили текст относительно простой программы, но зато она поможет нам быстро прогрессировать в понимании СОМ. Следующий текст программы представляет собой реализацию класса C++ для фабрики классов.

После сохранения предыдущего файла МАТН.СРР создайте новый и назовите его SERVER.CPP. Этот файл будет содержать главную программу реализации хранилища нашего компонента. Файлы IMATH.H, МАТН.Н и МАТН.СРР хранят тексты программ компонента. Теперь приведем код, с помощью которого наш компонент помещается в хранилище.

Вначале мы включили в программу файл заголовков INITGUID.H, чтобы определить GUID, используемый в DLL-файле. Затем определили две глобальные переменные, отвечающие за подсчет обращений к хранилищу компонента. Имейте в виду: для того чтобы DLL-файл стал настоящим хранилищем компонентов, стандарт СОМ требует наличия В нем как минимум двух функций (на самом деле их четыре, но остальные две будут рассмотрены в следующих примерах). Сначала реализуем функцию DllGetClassObject. СОМ вызывает эту точку входа по требованию клиента компонента. Указанная функция проверяет, поддерживается ли затребованный клиентом компонент DLL-файлом. Удостоверившись в этом, мы создаем экземпляр фабрики классов для объекта Math и вызываем функцию QueryInterface из интерфейса, затребованного клиентом. Фабрика классов объекта Math поддерживает только интерфейсы IUnknown и IClassFactory. Если клиент или СОМ требует какой-либо другой интерфейс, то возвращается код ошибки. Благодаря двум глобальным переменным реализация функции DllCanUnloadNow намного упростилась. Проверяем, имеются ли ожидающие обработки экземпляры компонента Math, и подсчитываем количество вызовов функции LockServer. Если какая-либо из проверок дает положительный результат, DLL-файл не может быть выгружен.

Остался всего один шаг. Чтобы сделать обе функции, определенные в файле SERVER.CPP, доступными для общего пользования, требуется создать файл определений SERVER. DEF и ввести в него следующие строки:

; ; Server.def : Declares the module parameters for the DLL. ; LIBRARY «SERVER»

DESCRIPTION ‘SERVER Windows Dynamic Link Library’

EXPORTS ; Имена точек входа для внешнего пользования помещаются здесь DllGetClassObject PRIVATE DllCanUnloadNow PRIVATE

Прежде чем создавать проект, используйте элемент Files into project. меню Insert для включения в проект файлов МАТН.СРР, SERVER.CPP и SERVER. DEF, и лишь после этого приступайте к созданию проекта. Последним шагом будет регистрация компонента Math. К этой статье прилагается файл SERVER.REG, который выглядит следующим образом:

REGEDIT HKEY_CLASSES_ROOT\Math.Component.1 = Chapter 6 Math Component HKEY_CLASSES_ROOT\Math.Component.1\CurVer = Math.Component.1 HKEY_CLASSES_ROOT\Math.Component.1\CLSID = HKEY_CLASSES_ROOT\CLSID\ = Chapter 6 Math Component HKEY_CLASSES_ROOT\CLSID\ \ProgID = Math.Component.1 HKEY_CLASSES_ROOT\CLSID\ \VersionIndependentProgID = Math.Component HKEY_CLASSES_ROOT\CLSID\ \InprocServer32 = c:\book\chap6\server\debug\server.dll HKEY_CLASSES_ROOT\CLSID\ \NotInsertable

Если вы использовали в примере имеющиеся GUID, то вам потребуется изменить только информацию о расположении SERVER.DLL в файле SERVER.REG в разделе InProcServer32. Однако если были сгенерированы собственные GUID, необходимо во всех строках, содержащих CLSID, обновить значения GUID. После того как вы введете необходимую информацию или обновите файл SERVER.REG, включите, его в реестр с помощью утилиты REGEDIT или дважды щелкните на названии этого файла в окне Windows Explorer.

ПРИМЕЧАНИЕ
В Windows95 и Windows NT существуют программы редактирования реестра REGEDIT.EXE и REGEDIT32.EXE. Зарегистрировать REG-файл можно, дважды щелкнув на его пиктограмме в окне Windows Explorer. Можно также ввести в командной строке start server.reg.

Теперь, после создания простого компонента Math, требуется организовать доступ к нему из приложения клиента, чтобы проверить, как он функционирует.

После этого мы создадим файл CLIENT.CPP и включим в него следующую программу:

В начале программы мы поместили файл заголовков IMATH.H из проекта сервера. Для определения GUID компонентов перед ним включен файл INITGUID.H. Функция main в первую очередь обеспечивает инициализацию библиотеки СОМ. В примере для определения CLSID используется ProgID компонента. Однако, прежде чем мы сможем вызвать CLSIDFromProgID, необходимо преобразовать ProgID (для которого используется кодировка ANSI) в строку с кодировкой Unicode. Все вызовы СОМ, OLE и ActiveX имеют встроенные реализации Unicode. Поэтому до передачи строк в любую API-функцию СОМ они должны быть преобразованы в вызовы с кодировкой Unicode.

После получения CLSID компонента вызываем функцию CoGetClassObject и запрашиваем указатель на интерфейс фабрики классов для компонента Math. После этого с помощью вызова CreateInstance создаем экземпляр компонента Math. Затем освобождаем интерфейс фабрики классов. Функция CreateInstance возвращает указатель на интерфейс IUnknown, с помощью которого мы в конце концов запрашиваем IMath. Получив указатель на него, используем сервисы компонента для выполнения некоторых простых операций.

По окончании всего этого мы освобождаем указатель на интерфейс IMath и вызываем CoUninitialize (это необходимо сделать до завершения работы приложения).

После ввода описанной выше программы включите в проект клиента файл CLIENT.CPP и постройте приложение. При пошаговой отладке клиента можно дойти даже до текста программы сервера. Не пожалейте времени и хорошо разберитесь в этих простых примерах клиента и сервера СОМ. Данные примеры помогут вам понять, что представляет собой СОМ-разработка.

Технология объектно-ориентированного подхода CORBA

(Common Object Request Broker Architecture — общая архитектура брокера объектных запросов)– это набор спецификаций, возникающий в результате самого широкого обсуждения накопившихся реальных проблем, в котором участвуют и разработчики и потребители технологий. В результате такого обсуждения создается документ, предлагающий решение рассматриваемых вопросов на уровне существующих технологий и технологий ближайшей перспективы. Достоинством опережающей разработки спецификации по сравнению с реализацией является возможность для независимых разработчиков создавать потенциально совместимые продукты, не ограничивая свободы выбора языков, ОС, аппаратных платформ, и не диктуя выбора конкретного технологического решения.

Альтернативные подходы, наиболее ярко выраженные в политике Microsoft и Sun, не соответствуют современным тенденциям развития технологий, согласно которым диктат одного производителя (хотя бы и с самыми лучшими намерениями) в общем, создает больше проблем, чем решает. Здесь имеются в виду не только технологии. Примером этого служит ОС Windows, которая имеет больше пользователей, чем все остальные вместе взятые, и при этом большинство рассматривает этот выбор как вынужденный.

Любой частный стандарт, поддерживаемый отдельным производителем (оставляя в стороне вопрос о его открытости) вынужден следовать исторически сложившейся линии развития, что рано или поздно входит в противоречие с интересами потребителя.

Проблема монопольных стандартов состоит в заведомо протекционистской политике владельца стандарта, проявляющейся на других связанных рынках, в случае с Microsoft, это ОС. Усиленное продвижение СОМ на платформе Windows делает перенос этого стандарта на другие платформы экономически невыгодным, заставляя разработчика вступать в заведомо проигрышную конкуренцию с Microsoft.

CORBA является концепцией, а не ее реализацией. Когда мы говорим «COM», то понимаем под этим скорее набор конкретных средств – элементов операционной системы, библиотек, утилит и т.п., являющихся составной частью того, что называется Microsoft Windows. Под термином «CORBA» понимается именно сложная и развитая концепция, сформулированная на уровне специального языка описаний – IDL. Реализации же этой концепции могут сильно отличаться друг от друга по различным критериям, наиболее важным в том или другом случае. VisiBroker (разработки Visigenic/Borland/Inprise/Corel) и Application Server, BEA WebLogic, Iona Orbix, Oracle Application Server и «картриджи» Oracle, IBM BOSS – все эти продукты используют те или иные возможности CORBA.

Под «стандартом» применительно к CORBA понимается то, что официально утверждено консорциумом OMG. Надо сказать, что это очень высокий уровень «легитимности», так как авторитет OMG в компьютерном мире чрезвычайно высок. OMG представляет собой некоммерческую организацию, являющуюся содружеством разработчиков программного обеспечения и его потребителей, объединивших свои усилия для создания спецификаций этой технологии. В настоящий момент в OMG состоит более 800 членов, включая всех сколько-нибудь серьезных производителей программного обеспечения (и даже c недавнего времени Microsoft). Первая спецификация CORBA появилась в 1991 г. Новые возможности официально считаются добавленными в CORBA в момент утверждения соответствующей спецификации. Как правило, в разработке спецификации участвуют крупнейшие специалисты в данной области. Разработка реализации – задача конкретной фирмы. Обычно от утверждения спецификации до появления высококачественной реализации проходит довольно много времени – иногда несколько лет. В настоящий момент стандартизовано отображение языка IDL на 6 языков программирования – Ada, C, C++, Cobol, Java и Smalltalk. Существуют также отображения на Pascal (точнее, Delphi), Perl, Python и еще несколько языков, но они не стандартизованы.

Объекты CORBA можно рассматривать как экземпляры (instances) некоторого метатипа, причем и метатип, и сами объекты существуют вне связи с конкретной программой на конкретном языке. Этот метатип в CORBA называется «интерфейсом».

К счастью, для новичка в мире CORBA понять, что же такое интерфейс, не составляет никакого труда.

Интерфейс в CORBA – это логически сгруппированный набор методов и атрибутов. Каждому интерфейсу присваивается имя, уникальное в пределах одной распределенной системы. В отличие от СОМ в CORBA нет бинарного стандарта интерфейсов. Вместо этого существует стандартный язык описаний IDL. Так уж получилось, что языки с названием IDL существуют в трех различных технологиях – OSF/DCE, Microsoft/COM и OMG/CORBA. Эти языки во многом похожи, поскольку предназначены для одного и того же, но OMG/IDL несколько отличается от своих «однофамильцев».

За его основу был взят язык C++ (его описательная часть и директивы препроцессора), поэтому читатель, знакомый с C++, при работе с IDL будет чувствовать себя вполне комфортно.

Вот пример объявления интерфейсов на языке IDL:

В настоящий момент последним стандартом CORBA является стандарт версии 2.3. В нем понятия «объект» и «интерфейс» связаны, так сказать, отношением «один к одному» – один объект не может поддерживать несколько интерфейсов. В стандарте CORBA 3.0, принятие которого ожидается к концу 2000 г, должна появиться возможность создания объектов, поддерживающих несколько интерфейсов.

С помощью приведенного выше примера определения интерфейса (и, естественно, определенного программного кода) вы можете, предположим, создать 5 объектов типа MyBaseInterface и 10000 объектов MyDerivedInterface. Каждый из этих объектов сопоставлен со своим типом и, кроме этого, имеет свой уникальный идентификатор.

Еще раз повторим – создание вышеуказанных 10005 объектов в общем случае никак не связано с «захватом» ни ресурсов компьютера (в первую очередь памяти), ни сетевых ресурсов.

Итак, вы можете создать CORBA-объект и даже установить с ним связь. В общем случае этого совершенно недостаточно, чтобы использовать его в конкретной программе. Функциональность CORBA-объекта недоступна для клиента до тех пор, пока в программе (серверном приложении) не создан объект, который позволяет получить доступ к методам, объявленным в IDL-интерфейсе. Этот объект (реализованный на C++, Java, C, Cobol, Ada, Smalltalk или некоторых других языках) и называется «сервантом».

Конечно, в зависимости от используемого языка программирования, серванты реализуются по-разному. Для объектно-ориентированных языков сервант является экземпляром (instance) некоторого класса, методы которого реализуют нужную функциональность. Такой класс часто называют «классом реализации».

За время существования CORBA-объекта с ним может быть сопоставлено множество различных реализаций сервантов (но не более одного за раз). Более того, они могут содержаться в адресном пространстве различных приложений. Эти приложения могут быть даже запущены на различных компьютерах.

Часто говорят, что сервант является «инкарнацией» CORBA-объекта. Связь между сервантами и CORBA-объектами является хотя и строго формализованной, но очень гибкой. Сервант может быть создан раньше или позже CORBA-объекта; один сервант может «обслуживать» как один, так и несколько (иногда сотни тысяч и миллионы) CORBA-объектов. Явное разделение циклов жизни CORBA-объектов и их сервантов (а именно серванты потребляют реальные ресурсы) – один из столпов, на которых базируется очень высокая масштабируемость CORBA-приложений.

Единственная сложность, связанная с пониманием смысла термина «объектная ссылка», состоит в том, что он используется в двух различных смыслах.

Есть объектная ссылка «мира CORBA», которая представляет собой закодированную информацию о CORBA-объекте. Она включает имя хоста, порта TCP/IP (или координаты Репозитария Реализаций), конечно же, уникальный идентификатор данного CORBA-объекта и множество другой информации, позволяющей клиенту установить связь с серверным объектом через границы языков программирования, операционных систем и аппаратных платформ. Операции с объектной ссылкой невозможны для клиента, за исключением того, что клиент может превратить ее в строку и записать в файл или базу данных. Впоследствии кто угодно может считать такую строку и преобразовать ее опять в объектную ссылку.

В другом понимании «объектная ссылка» – это переменная того или иного языка программирования, с помощью которой клиент осуществляет вызов удаленных методов. В последующих разделах будут приведены примеры получения и использования такой объектной ссылки. В дальнейшем все упоминания объектных ссылок относятся именно к этому, второму, типу объектных ссылок.

Концептуально переменная типа «объектная ссылка» является указателем на так называемый «proxy-объект», который существует на стороне клиента и обеспечивает выполнение удаленных вызовов. Сам proxy-объект сделан недоступным для программиста; связано это с тем, что его создание – задача не клиентского приложения, а самого ORB’а. Логически с каждым proxy-объектом сопоставлена отдельная объектная ссылка, и под копированием объектной ссылки следует понимать создание как нового proxy-объекта, так и настроенного на него нового «указателя». Разумеется, в реальных реализациях физического копирования proxy-объекта не происходит – как всегда в таких случаях, используется механизм счетчика ссылок.

Очень важно отчетливо понимать, что копирование (или уничтожение) объектных ссылок на стороне клиента влияет исключительно на клиентское приложение. Неправильное ведение счетчика ссылок в самом худшем случае приведет к продолжению физического существования в клиентском приложении ненужного proxy-объекта. Никакого отношения к серверному объекту эти действия не могут иметь в принципе. И создание, и уничтожение сервантов или серверных CORBA-объектов – задача серверного приложения. Философия CORBA состоит в том, чтобы клиент посылал сообщения «установить связь с существующим объектом» и «разорвать с ним связь», а не «создать серверный объект» и «уничтожить его». Разумеется, клиент может инициировать создание Corba-объектов вызвав у удаленного объекта специально предусмотренный для этого программистом (автором объекта) метод.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *