Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Учебное пособие 2144

.pdf
Скачиваний:
8
Добавлен:
30.04.2022
Размер:
7.67 Mб
Скачать

Если требуется только один экземпляр кокласса, то можно использовать метод СоCreateInstance(). Метод СоCreateInstance() находит объект класса и автоматически вызывает CreateInstance() из указателя IСlassFactory. От программиста требуется передать нужные CLSID и IID. При использовании СоCreateInstance() объект каждый раз создаётся и каждый раз удаляется.

1.2.6. Язык определения интерфейса MIDL

MIDL – (Microsoft Interface Definition Language) яв-

ляется расширением существующего IDL для поддержки СОМ.

Описание СОМ-сервера помещается в файл *.idl и обрабатывается компилятором midl.exe. Использование MIDL обеспечивает языковую независимость и прозрачность местонахождения сервера. Файл *.idl создаётся в среде Visual C++ и автоматически компилируется при сборке проекта.

Основные типы данных IDL (см. таблицу) похожи на их аналоги в языке С. Это язык определений. В нём отсутствуют циклы и условные операторы.

31

 

Таблица

 

Ключевые слова MIDL

Ключевое

Описание

слово

 

typedef

Аналогично слову typedef языка С.

 

 

import

Вносит существующие IDL-определения в

 

IDL-файл. Аналогично директиве #include

 

языка С. Пример:

 

import “ouidl.idl” // включает ин-

 

терфейсы автоматизации.

object

Определяет, что далее следуют определения,

 

относящиеся к СОМ.

interface

Объявление нового СОМ-интерфейса.

cpp-quote

Вставка строки в программу на С\С++, гене-

 

рируемую компилятором MIDL (это строка -

 

комментарий).

uuid

Универсальный уникальный идентификатор

 

(то же, что и GUID).

helpstring

Вставка строки комментария.

 

 

enum,

Создание перечисления, vl_enum означает 32-

vl_enum

битные перечисления

library

Оператор библиотеки типов с обязательным

 

атрибутом uuid определяет, какие коклассы

 

содержатся в сервере (ЕХЕ или DLL - библио-

 

теке).

importlib

Импорт в откомпилированную библиотеку.

 

Должна, как минимум, импортироваться

 

стандартная библиотека типов stdole32.tlb.

32

 

Продолжение таблицы

Ключевое

Описание

слово

 

[in]

Атрибут параметра метода, передаваемого от

 

клиента к серверу (параметр, задаваемый по

 

умолчанию).

[out]

Атрибут параметра метода, передаваемого от

 

сервера к клиенту.

 

Клиент освобождает память полученных дан-

 

ных. Параметр [out] – это всегда указатель.

[in, out]

Посылка от клиента к серверу. Клиент отво-

 

дит и освобождает память, но сервер тоже

 

может управлять памятью при вызове метода.

coclass

Объявление кокласса в библиотеке, uuid –

 

обязателен.

default

Определение интерфейса по умолчанию. Ка-

 

ждый кокласс должен иметь ровно один ин-

 

терфейс по умолчанию. Используется для ра-

 

боты с С\С++.

Пример определения интерфейсов сервера CarServer средствами IDL.

import “oaidl.idl”

 

...

 

// ICreateCar

// IID

[object, uuid (...),

helpstring (“Create a car”)]

 

interface ICreateCar: IUnknown

 

{

 

33

HRESULT SetPetName ([in] BSTR petName);

HRESULT SetMaxSpeed ([in] int maxSp);

};

[uuid (...), //LIBID helpstring (“CoCar Server with TypeLib”)] library CarServer

{

importlib(“stdole32.tlb”); //должна

быть //первой строкой в

библиотеке

[uuid (...)]

//CLSID

coclass CoCar

 

{

 

[default] interface ICreateCar; interface IStats;

interface IEngine;

};

};

Файлы, генерируемые компилятором MIDL

Имена большинства генерируемых MIDL-файлов основаны на первоначальном имени IDL-файла. Для файла CarServer.idl, например, строятся следующие файлы.

CarServer.h – содержит определение интерфейса с использованием интерфейсных макросов СОМ.

CarServer_i.c – содержит все определения GUID. Для каждого атрибута [uuid] формируется соответствующая константа с префиксом IID_ , CLSID_ или

LIBID_.

CarServer.tlb – двоичный эквивалент текста IDL, который называется библиотекой типов. Важно, что программы и на других языках, кроме С\С++, могут ис-

34

пользовать содержащиеся в них коклассы, интерфейсы и пользовательские типы.

CarServer_p.c и dlldata.c – используются для формирования dll, содержащего заглушки/прокси для удалённого доступа к СОМ-интерфейсам.

Для того чтобы другие языки могли получить информацию о типе сервера, надо ввести информацию о файле *.tlb в системный реестр под ключом

HKEY_CLASSES_ROOT/TypeLib.

1.3.Технология DCOM

1.3.1.Организация обмена между клиентом

исервером (маршалинг)

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

Процедура обмена между клиентом и локальным или удаленным сервером посредством использования заглушек и прокси называется маршалингом. Коды заглушек и прокси генерируются для всех определенных на IDL интерфейсов. Маршалинг осуществляется с помощью механизма удаленного вызова процедур (RPC).

Заглушка-объект – это СОМ-объект, загруженный в процесс сервера, который получает запросы клиента и передает реальному объекту.

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

35

стандартные СОМ-интерфейсы. Прокси располагаются внутри процесса клиента и предоставляют клиенту локальные или удаленные интерфейсы.

Следующий посредник на пути между клиентом и сервером – объект канала ORPC (Object RPC). Объект канала поддерживает интерфейс IRpcChannelBuffer. Этот интерфейс разбивает на пакеты запросы клиента и посылает их заглушке, используя вызовы RPC низкого уровня.

Прокси поддерживает интерфейс IRpcProxyBuffer. Этот интерфейс используется для установления или разрыва связи между прокси-объектом и объектом канала.

IRpcProxyBuffer содержит два метода: Connect() и Disconnect(). Метод Connect() в качестве пара-

метра принимает указатель интерфейса IRpcChannelBuffer.

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

36

Пространство процесса клиента

IRpcProxyBuffer

Клиент,

IDraw

имеющий

pDraw

IDraw

 

 

IRpcChannelBuffer

 

Канал к CoHex-

 

agon Draw

 

IUnknown

 

Передача запроса заглушке ин-

 

терфейса IDraw кокласса CoHex-

 

agon c помощью ORPC

Рис. 1.7. Связь между клиентом, прокси

 

и объектом канала

Прокси-объекты поддерживают IRpcProxyBuffer, позволяющий им связываться с объектом канала. На серверной стороне объект-заглушка реализует стандартный СОМ-интерфейс IRpcStubBuffer, который аналогично интерфейсу IRpcProxyBuffer тоже поддерживает методы Connect() и Disconnect(). Запрос, полу-

ченный от объекта канала ORPC, направляется заглушкой серверу (см. рис. 1.8) .

Схема вызова метода удаленного интерфейса показана на рис. 1.9.

37

Менеджер

Пространство процесса сервера

IUnknown

IUnknown

IDra

 

IDrawStub

 

IRpcStubBuffer

 

IUnknown

CoHexagon

IShapeEditStub

 

IRpcStubBuffer

IShapeEdit

 

 

Реализация CoHexagon::Draw()

Рис. 1.8. Заглушки реализуют IrpcStubBuffer для распаковки запроса и передают

его реальному СОМ-объекту

38

Клиент

 

 

 

IUnknow

 

 

 

 

pDraw

IRpcProxyBuffer

 

IDrawStub

 

 

 

 

IDraw

IDrawProxy

IRpcStubBuffe

 

 

 

IUnknow

 

 

 

 

IRpcChannelBuffe

Канал к IDraw

CoHexago

кокласса CoHex

n

 

 

 

 

 

 

IDraw

Рис. 1.9. Схема вызова метода удалённого интерфейса

39

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

ры вызывают метод CreateProxy() или CreateStub() ин-

терфейса IPSFactoryBuffer. Далее прокси и заглушка загружаются в процессы клиента и сервера.

В процессе установки пограммы-сервера, то есть всем коклассам, присутствующим в исполняемом файле, присваивается идентификатор приложения AppID (GUID).

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

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

Кроме того, надо перекомпилировать клиент с флагом

CLSCTX_LOCAL_SERVER в методе CoGetClassObject().

1.3.2. Виды маршалинга в модели СОМ

Имеется три основных способа обмена информацией между процессами.

1. Пользовательский маршалинг. Реализуется стандартный интерфейс IMarshal, не используется ORPC, программист самостоятельно разрабатывает программы обмена. Это сложный способ обмена.

40