Сущность технологии СОМ. Библиотека программиста

ОглавлениеДобавить в закладки К обложке

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

Простейший способ выразить диспинтерфейс на IDL – это использовать ключевое слово dispinterface:

[uuid(75DA6450-DD0F-11d0-8C58-0880C73925BA)] dispinterface DPrimeManager {

properties: [id(1), readonly] long MinPrimeOnMachine;

[id(2)] long MinPrime;

methods: [id(3)] long GetNextPrime([in] long n);

}

Этот синтаксис вполне читабелен; однако он предполагает, что вызывающая программа будет всегда обращаться к свойствам и методам объекта через IDispatch. История показала, что по мере развития программных сред этапа разработки и выполнения они часто становятся способными использовать обычные интерфейсы СОМ. Для обеспечения того, чтобы обращение к диспинтерфейсу было успешным и в будущих средах подготовки сценариев, как правило, лучше моделировать интерфейс как двойственный, или дуальный (dual interface).

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

[object, dual, uuid(75DA6450-DD0F-11d0-8C58-0080C73925BA)] interface DIPrimeManager : IDispatch {

[id(1), propget]

HRESULT MinPrimeOnMachine( [out, retval] long *pval); [id(2), propput]

HRESULT MinPrime([in] longval);

[id(2), propget] HRESULT MinPrime([out, retval] long *pval);

[id(3)] long GetNextPrime([in] long n);

}

Заметим, что этот интерфейс наследует IDispatch, а не IUnknown. Также отметим, что данный интерфейс имеет атрибут [dual] . Этот атрибут заставляет сгенерированную библиотеку типов включить в себя диспетчерский вариант интерфейса, который совместим со средами, не поддерживающими двойственные интерфейсы. Атрибут [dual] относится к категории атрибутов [oleautomation] и также заставляет сгенерированную библиотеку типов добавлять ключи реестра для универсального маршалера во время выполнения RegisterTypeLib.

Если интерфейс определен как двойственный, то реализация методов IDispatch является тривиальной. Дело в том, что синтаксический анализатор библиотеки типов реализует два из четырех методов IDispatch . Если двойственный интерфейс был определен заранее, объекту необходимо на этапе инициализации просто загрузить библиотеку типов: class PrimeManager:

DIPrimeManager { LONG m_cRef;

// СОМ reference count

// счетчик ссылок СОМ ITypeInfo *m_pTypeInfo;

// ptr. to type desc.

// указатель на описание типов

// IUnknown methods…

// методы IUnknown…

// IDispatch methods…

// методы IDispatch…

// IPrimeManager methods…

// методы IPrimeManager…

PrimeManager(void) : m_cRef(0) {

ITypeLib *ptl = 0;

HRESULT hr = LoadRegTypeLib(LIBID_PrimeLib, 1, 0, 0, &ptl);

assert(SUCCEEDED(hr));

hr = ptl->GetTypeInfoOfGuid(IID_DIPrimeManager, &m_pTypeInfo);

ptl->Release(); } virtual PrimeManager(void) { m_pTypeInfo->Release(); }


Логин
Пароль
Запомнить меня