Диспетчерские интерфейсы и автоматизация

Автоматизация это другой способ управления компонентом. Автоматизация – надстройка над COM.

Сервер Автоматизации – это компонент СОМ, который реализует интерфейс IDispatch.

Контроллер Автоматизации –  это клиент СОМ, взаимодействующий с сервером через интерфейс IDispatch. (Для вызовы функций сервера использует функции члены интерфейса – неявный вызов).

Первоначально Автоматизация разрабатывалась для Visual Basic.

Почти любой сервис, представимый через интерфейсы COM может быть представлен и через IDispatch.

Интерфейс IDispatch

IDispatch предоставляет доступ ко всем сервисам через один единственный интерфейс.

IDispatch обеспечивает вызов функции по трем параметрам:  ProgID компонента, имени функции и ее аргументов.

Интерфейс  IDispatch имеет следующее формальное описание:

interface IDispatch : IUnknown                                   //из файла OAidl.idl

   {

    HRESULT GetTypeInfoCount([out] UINT* pctinfo) ;

 

    HRESULT GetTypeInfo ([in] UINT iTInfo,
                        [in] LCID lsid;;
                        [out] ITypeInfo** ppTInfo) ;

 

HRESULT GetIDsOfName ([in] REFIID riid,   // Принимает имя функции и

                                                                             // возвращает ее
                        [in, size_is(cNames)] LPOLESTR *rgszNames,  // Диспетчерский

                                                                                                      // идентификатор
                        [in] UINT cNames,
                        [in] LCID lcid,
                        [out, size_is(cNames)] DISPID *rgDispId) ;       // DISPID это длинное

                                                                                       // целое

                                                                                       // LONG и не уникально

 

//У каждой реализации IDispatch имеется свой собственный IID (иногда называется DIID).

 

HRESULT Invoke ([in] DISPID dispIdMember,   // Контроллер автоматизации
                        [in] REFIID riid,                               // передает DISPID вызываемой

                                                                                   // функции в Invoke

                        [in] LCID lsid,

                        [in] WORD wFlags,

                        [in, out] DISPPARAMS* pDispParams,

                        [out] VARIANT* pVarResult,

                        [out] EXEPINFO* pExcepinfo,

                        [out] UINT* puArgErr

                             );

 

DISPID используется функцией-членом Invoke как индекс в массиве указателей на функции. Однако, сервер Автоматизации не обязан реализовывать Invoke именно таким образом. Он может использовать обычный оператор switch.

IDispatch::Invoke реализует набор функций, доступ к которым осуществляется по индексу.

Набор функций, реализованных с помощью IDispatch::Invoke называется диспетчерским интерфейсом (disp-интерфейсом)

Реализация IDispatch::Invoke определяет набор функций, посредством которых взаимодействую сервер и контроллер автоматизации.

 

Пример возможной реализации DISP-интерфейса:

 

 

 

Интерфейс IDispatch

 

 

DISP-интерфейс

 

 

 

 

 

 

 

 

IDispatch* ->

pVtbll  ->

&QueryInterface

 

 

DISPID Массив имен

 

pIDispatch

 

&AddRef

 

                    a

1                F1

 

 

 

&Release

 

ф-ия

2                F2

 

 

 

&GetTypeInfoCount

 

GetDsOfNames

3                F3

 

 

 

&GetTypeInfo

 

 

 

 

 

 

&GetDsOfNames

 

 

DISPID   Массив

 

 

 

&Invoke

 

 

указателей

 

 

 

 

 

ф-ия

на функции

 

 

 

 

 

Invoke   ?

1                &F1

 

 

 

 

 

 

2                 &F2

 

 

 

 

 

 

3                 &F3

 

 

 

 

 

 

 

 

 

Дуальные интерфейсы

Если интерфейс COM, реализующий IDispatch::Invoke наследует не IUnknown, а IDispatch, то такой интерфейс называется дуальным интерфейсом.

Дуальный интерфейс  – это disp-интерфейс все члены которого, доступные посредством вызова метода Invoke, доступны и напрямую через таблицу виртуальных функций vtbl.

Следующая схема иллюстрирует различные способы применения функции Invoke (при наследовании от IUnknown и при наследовании от IDispatch).

 

 

Интерфейс IDispatch

 

 

 

DISP-интерфейс

 

 

 

 

 

 

 

 

 

IDispatch* -> pIDispatch

pVtbll  ->

&QueryInterface

 

 

 

DISPID    Массив имен

 

 

 

&AddRef

 

 

 

1               F1

 

 

 

&Release

 

ф-ия

 

2               F2

 

 

 

&GetTypeInfoCount

 

GetDsOfNames

 

3               F3

 

 

 

&GetTypeInfo

 

 

 

 

 

 

 

&GetDsOfNames

 

 

 

 

 

 

 

&Invoke

 

 

 

 

 

 

 

 

 

ф-ия

 

Интерфейс F3 (СОМ)

 

 

 

 

 

Invoke  ->

pVtbl ->

&F1

 

 

 

 

 

 

 

&F2

 

 

 

 

 

 

 

&F3

 

 

 

 

 

 

 

 

 

Реализация IDispatch::Invoke с помощью интерфейса СОМ.

 

 

Интерфейс F3 наследует интерфейсу IDispatch

 

 

 

DISP-интерфейс

 

 

 

 

 

 

 

 

 

IDispatch*->

pVtbll  ->

&QueryInterface

 

 

 

DISPID    Массив имен

 

pIDispatch

 

&AddRef

 

 

 

1                   F1

 

 

 

&Release

 

ф-ия

 

2                   F2

 

 

 

&GetTypeInfoCount

 

GetDsOfNames

 

3                  F3

 

 

 

&GetTypeInfo

 

 

 

 

 

 

 

&GetDsOfNames

 

 

 

 

 

 

 

&Invoke

->

ф-ия Invoke

 

 

 

 

 

&F1

 

a

 

 

 

 

 

&F2

 

 

 

 

 

 

 

&F3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Реализация IDispatch::Invoke с помощью дуального интерфейса.

 

Вызовы через дуальные интерфейсы быстрее выполняются и их легче реализовывать. Основное ограничение – набор типов параметров.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100