Программирование интерфейсов объектов 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Программирование интерфейсов объектов



СОМ-интерфейсы

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


Пользователь СОМ-объекта

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


СОМ-классы
СОМ со-классы (coclass) - это классы, которые содержат один или более СОМ-интерфейс. Вы можете не обращаться к СОМ-интерфейсу непосредственно, а получать доступ к СОМ-интерфейсу через со-класс. Со-классы идентифицируются при помощи идентификаторов класса (CLSID).

 
Библиотеки типов

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

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



Рис. 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

       
  Значение Описание  
  S_OK Интерфейс поддерживается  
  E_NOINTERFACE Интерфейс не поддерживается  
  E_UNEXPECTED Неизвестная ошибка  
       

 


Указатели СОМ-интерфейса

Указатель интерфейса - это 32-битный указатель на экземпляр объекта, который является, в свою очередь, указателем на реализацию каждого метода интерфейса. Реализация методов доступна через массив указателей на эти методы, который называется vtable. Использование массива vtable похоже на механизм поддержки виртуальных функций в Object Pascal.


Рис. 3.2. Схема работы указателя СОМ-интерфейса

Наглядное представление работы указателей СОМ-интерфейса представлено на рис. 3.2.

Расширения СОМ

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

Технология ActiveX - это технология, которая использует компоненты СОМ, особенно элементы управления. Она была создана для того, чтобы работа с элементами управления была более эффективной. Это особенно необходимо при работе с приложениями Internet/Intranet, в которых элементы управления должны быть загружены на компьютер клиента, прежде чем они будут использоваться.

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

 Постоянно идет доработка старых и создание новых, более совершенных технологий межпрограммного взаимодействия.

 

Таблица 3.2. Список расширений СОМ

       
  Расширение СОМ Краткое описание  
  Серверы автоматизации (Automation servers) Серверы автоматизации- это объекты, которыми можно управлять из других приложений во время работы приложения. Таким образом, автоматизация- это способность приложения программно контролировать объекты других приложений  
  Диспетчеры автоматизации или СОМ-клиенты (Automation Controllers, COM Clients) Диспетчеры автоматизации- это клиенты серверов автоматизации. Они позволяют разработчику или пользователю писать сценарии для управления серверами автоматизации  
  Элементы управления ActiveX (ActiveX Controls) Элементы управления ActiveX предназначены для серверов внутри процесса (in-process COM servers). Элементы ActiveX обычно используются путем встраивания в приложение-клиент  
  Библиотеки типов (Type Libraries) Библиотеки типов представляют собой статичные структуры данных, которые часто сохраняются как файлы ресурсов. Они содержат детализированную информацию об объекте и его интерфейсах. Клиенты серверов автоматизации и элементы управления ActiveX используют данную информацию и всегда считают ее доступной  
  Страницы активного сервера (Active Server Pages) Активные серверные страницы- это компоненты ActiveX, которые позволяют вам создавать динамически изменяющиеся Web-страницы  
  Активные документы (Active Documents) Активные документы - это объекты, которые поддерживают связывание и внедрение, визуальное редактирование, перенос (drag-and-drop). В качестве примера таких документов можно представить документы Microsoft Word и книги Microsoft Excel  
  Визуальные межпроцессные объекты (Visual Cross-process Objects) Визуальные межпроцессные объекты- это визуальные объекты, которыми можно управлять из других процессов  
       


На рис. 3.7 представлена диаграмма, которая показывает связь некоторых расширений СОМ и их связь с технологией СОМ.

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



Рис. 3.7. Технологии, основанные на СОМ

 

Язык C++, компоненты и интерфейсы

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

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

class Math { // описание интерфейса public: long Add(long Op1, long Op2); long Subtract(long Qp1, long Op2); long Multiply(long Op1, long Ор2); long Divide(long Op1, long Op2);   private: // реализация string m_strVersion; string get_Version(); };   long Math::Add(long Op1, long Op2) { return Op1 + Op2; }   long Math::Subtract(long Op1, long Op2) { return Op1 - Op2; } long Math::Multiply(long Op1, long Op2) { return Op1 * Op2; } long Math::Divide(long Op1, long Op2) { return Op1 / Op2; }

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

class IMath { public: virtual long Add(long Op1, long Op2) = 0; virtual long Subtract(long Op1, long Op2) = 0; virtual long Multiply(long Op1, long Op2) = 0; virtual long Divide (long Op1, long Op2) = 0; };

Затем мы создадим производный класс и опишем его методы точно так же, как это делалось раньше:

class Math: public IMath { public: long Add(long Op1, long Op2); long Subtract(long Op1, long Op2); long Multiply(long Op1, long Op2); long Divide (long Op1, long Op2); };

Это лишь первый шаг в преобразовании класса C++ в объект, доступный для программ, написанных на других языках. СОМ-технологии, такие как OLE и ActiveX, в основном реализуются посредством интерфейсов типа рассмотренного нами ранее класса IMath. Наш новый класс является абстрактным, т.е. он содержит, по крайней мере, одну чисто виртуальную функцию и одни лишь методы (без каких-либо данных) компонентного объекта.

Начальная буква "I" в названии класса IMath отражает тот факт, что он является объявлением интерфейса. Такие обозначения используются в технологии программирования СОМ повсеместно. Класс IMath объявляет внешний интерфейс для компонента Math. Наиболее важным аспектом этого нового класса является его способность порождать виртуальную таблицу функций C++ (Vtable) в любом производном классе.

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

В технологии СОМ доступ к компонентам обеспечивается только с помощью указателей на виртуальные таблицы. Таким образом, прямой доступ к конкретным данным компонента становится невозможным. Внимательно изучите наш пример. Он достаточно прост, но отражает ключевую концепцию СОМ — использование виртуальных таблиц для доступа к функциональным возможностям компонента. Наконец, СОМ-интерфейс представляет собой просто указатель на указатель виртуальной таблицы (virtual table, или Vtable) C++. На рис. 1 отражено это взаимоотношение для случая компонента Math.

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


Рис. 1. Виртуальная таблица функций и СОМ-интерфейс

Во-вторых, Microsoft движется в направлении от создания библиотек функций (например, Win32 API) к созданию компонентов операционной системы, предоставляющих определенные СОМ-интерфейсы. В таком случае вы становитесь пользователем компонента. Вместо функций API вы получаете интерфейс для компонента системы Windows и доступ к его функциям посредством СОМ-интерфейса. Это дает возможность заменять реализацию компонента операционной системы, не оказывая воздействия на другие компоненты и приложения.

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

Стандартные СОМ-интерфейсы

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

Интерфейс IUnknown выполняет две функции. Первая состоит в том, чтобы обеспечить стандартный способ запроса определенного интерфейса данного компонента его пользователем (клиентом). Эту возможность предоставляет метод QueryInterface. Вторая функция состоит в обеспечении способа управления временем жизни компонента извне. Интерфейс IUnknown предоставляет два метода (AddRef и Release), обеспечивающих управление временем жизни экземпляра компонента. Приведем определение IUnknown.

class IUnknown { public: virtual HRESULT QueryInterface(REFID riid, void** ppv)=0; virtual ULONG AddRef () = 0; virtual ULONG Release() = 0; };

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

Тип данных HRESULT

Большинство методов СОМ-интерфейса и функции API возвращают значение типа HRESULT (исключениями являются AddRef и Release). В Win32 тип данных HRESULT определяется как DWORD (32-битовое целое), а возвращаемое значение этого типа содержит информацию о результате вызова функции. Старший бит сигнализирует об успешном или ошибочном завершении работы функции, а следующие 15 битов идентифицируют тип ошибки и обеспечивают способ группировки однотипных кодов завершения; младшие 16 битов предоставляют специфическую информацию о происшедшем. Структура данных HRESULT идентична структуре значений флагов статуса, используемых функциями Win32 API.

Система разработки СОМ обеспечивает несколько макросов, помогающих узнать результат вызова метода. Макрос SUCCEEDED принимает значение TRUE при успешном вызове функции, а макрос FAILED принимает это же значение при ошибке вызова функции. Названные макросы не являются специфичными для СОМ и ActiveX, а используются повсеместно в среде Win32 и определяются в файле WINERROR.H. Возвращаемые значения в Win32 предваряются префиксом S_ в случае нормального завершения и префиксом Е_ — в случае ошибки.



Поделиться:


Последнее изменение этой страницы: 2021-05-27; просмотров: 102; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.21.233.41 (0.028 с.)