Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы к лекциям COM.doc
Скачиваний:
4
Добавлен:
18.04.2019
Размер:
880.64 Кб
Скачать

8. Стандарт бинарного интерфейса com

8.1. Основные определения

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

COM является бинарным стандартом по следующим причинам:

  1. COM позволяет создавать бинарные компоненты, которые могут быть использованы как локально, так в распределенном сетевом окружении;

  2. При описании CoClass каждого COM-объекта используется уникальный бинарный идентификатор CLSID, который может принадлежать только данному COM-объекту;

  3. Использование IDL не обязательно для описания интерфейсов (в отличие от CORBA).

Очень важный момент при описании бинарного стандарта – то что он позволяет повторно использовать компоненты, не переписывая их кода (так называемое свойство COM-объекта – агрегация).

Написанные программные компоненты будут соединяться вместе, но при этом их внутренняя реализация ничем не ограничена. Также наличие бинарного стандарта полагает, что ЛЮБАЯ реализация модели COM 100% совместима с другими моделями COM (это является необходимым условием того, чтобы модель была бинарна).

В бинарный стандарт входят:

  1. Клиент поддерживает указатель на интерфейс, который в свою очередь является указателем на указатель массива указателей на реализации методов;

  2. На данной платформе реализация данного метода конкретного интерфейса имеет фиксированное соглашение о вызове.

  3. К примеру, в Win32 используется стандартное соглашение о вызове (обозначается __stdcall), которое является гибридом C- и Pascal соглашений. Аргументы засылаются в стек, справа налево, но очищает стек сама вызываемая функция. Имена функций, следующих стандартному соглашению, предваряются символом _, а заканчиваются суффиксом @, за которым следует количество байт, передаваемых функции.

  4. Все строки, передаваемые через все интерфейсы COM-объектов, обязаны быть в формате Unicode.

При создании COM-объектов на C++ использование MIDL является стандартной практикой. Некоторые среды программирования (Delphi, VB) обходятся без MIDL. Delphi имеет свой, Паскале-подобный синтаксис, а в VB любой класс априори является COM-объектом и дополнительное описание не требуется. MIDL является развитием OSF DCE IDL и имеет обратную совместимость с ним.

Как видно из примера, MIDL-описание очень похоже на C++. Главные отличия MIDL от C++ в том, что MIDL позволяет задать только описание интерфейса, и в том, что MIDL содержит дополнительные атрибуты, помещаемые в квадратные скобки. Самым главным атрибутом интерфейса является uuid. Он задает IID интерфейса.

Ниже приведен пример описания интерфейса на MIDL.

[

uuid(F3792A83-69C9-11D2-AC8C-525400DDA17A),

helpstring("Этот интерфейс определяет методы работы со стеком.")

]

interface IStack : IUnknown

{

HRESULT Push([in] VARIANT Val);

HRESULT Pop([out, retval] VARIANT *pVal);

}

Основные функции idl:

  • Связь с языком;

  • Двоичный интерфейс приложения;

  • Сетевой интерфейс.

8.2. Доступ к com-объектам, работа с памятью

Для того, чтобы получить доступ к методам COM-объекта, необходимо получить указатель на его интерфейс, для этого могут быть выполнены следующие действия:

  1. Вызвать API-функцию, создающую объект одного типа и возвращающую указатель на интерфейс;

  2. Вызвать функцию члена через интерфейс другого объекта, указатель на который уже известен;

  3. Реализовать свой собственный интерфейс, через который другие объекты будут передавать указатель на свой собственный интерфейс;

  4. Вызвать API-функцию, которая по данному идентификатору класса объектов, создает объект, возвращаемый указатель на интерфейс.

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

  1. Уникально идентифицировать по имени API-функции, создающей объект;

  2. Уникально идентифицировать по позиции объекта в иерархии компоненты;

  3. Уникально идентифицировать по внутреннему имени класса интерфейса;

  4. Уникально идентифицировать по известному уникальному идентификатору CLSID.

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

Лучше передавать параметры по значению, данный вопрос рассматривался в теме про RPC. Для передачи параметров по указателю должно существовать специальное соглашение:

  1. Входной параметр ([in]) – память должна выделять вызывающая;

  2. Выходной параметр ([out]) – память должна выделять вызываемая, а освобождать вызывающая;

  3. Входной/выходной параметр ([in/out]) – память должна выделяться вызывающей, освобождаться также вызывающей, но при необходимости память может быть перевыделена вызываемой.

Сервис COM для распределение памяти задачи происходит через объект «распределитель», который поддерживает интерфейс malloc.

Также вводятся дополнительные правила для работы с памятью:

  1. Выходной параметр ([out]) – в случае ошибки указатель должен быть установлен в NULL;

  2. Входной/выходной параметр ([in/out]) – в случае ошибки, указатель можно как оставить без изменения, так и установить в NULL.