Двойственные интерфейсы
Технология Automation, ранее известная как OLE Automation, дает совершенно другой способ вызова клиентом методов, экспонируемых сервером, чем тот стандартный для СОМ способ, который мы уже рассмотрели. Вы помните, что он использует таблицу виртуальных указателей vtable на интерфейсы. Automation же использует стандартный СОМ-интерфейс IDispatch для доступа к интерфейсам. Поэтому говорят, что любой объект, поддерживающий IDispatch, реализует Automation. Также говорят о дуальном интерфейсе, имея в виду, что он может быть вызван как с помощью естественного способа (vtable), так и с помощью вычурного способа Automation. Итак, интерфейс IOpenGL предоставляет своим пользователям двойственный (dual) интерфейс.
Dual Interface понадобился для того, чтобы VBScript-сценарий мог использовать СОМ-объекты, созданные с помощью Visual C++. Клиенты, созданные на языке C++, могут с помощью Querylnterf асе получить адрес интерфейса и прямо вызывать его методы, пользуясь таблицей виртуальных функций (vtable), например:
p › SomeMethod(i, d);
В VBScript будут проблемы. Там нет строгого контроля соответствия типов и многие типы C++ ему неизвестны. Интерфейс IDispatch служит посредником в разговоре двух произведений Microsoft. Теперь программа на VBScript может добраться до метода SomeMethod, выполнив длинную цепь вызовов. Сначала она должна получить указатель на интерфейс IDispatch, затем с его помощью (GetiDsOf Names) узнать индекс желаемого метода (типа DISPID – dispatch identifier), на сей раз не 128-битный. После этого она сможет заставить систему выполнить коды метода SomeMethod, но не прямо, а с помощью метода IDispatch::Invoke, который требует задать 8 параметров, смысл которых может приблизительно соответствовать следующему списку описаний. Последующий текст воспринимайте очень серьезно, так как он взят прямо из справки IDispatch::invoke:
- вызовите пятую функцию из vtable, так как IDispatch:: GetIDsOfNames сообщил, что ее имяSomeMethod;
- возьмите неиспользуемый (пока) параметр;
- возьмите 32-битный описатель местности (LCID);
- возьмите флаг DISPATCH_METHOD | DISPATCH_PROPERTYGET, описывающий суть того, что запрашивается у пятой функции;
- возьмите адрес структуры DISPPARAMS, в которую завернут массив аргументов, массив индексов (DISPID) для них и числа, описывающие размеры массивов;
- возьмите адрес структуры VARIANT (из 49 полей, правда 47 из них union), в которой пятая функция может возвратить результат вызова, но только если в 4-м параметре (флаге) указано, что результат нужен;
- возьмите адрес структуры EXCEPINFO, в которую система в случае непредвиденных обстоятельств запишет причину отказа (сбоя);
- возьмите адрес переменной, в которой вернется индекс первого аргумента в массиве отказов, так как аргументы там хранятся в обратном порядке, а нам нужна ошибка с самым высоким индексом. Но если в HRESULT будет DISP_E_TYPEMISMATCH или DiSP_E_PARAMNOTFOUND, то возвращаемое значение недействительно.
(Поток сознания в скобках, по Джойсу или Жванецкому: новые концепции, новые технологии, глубина мыслей, отточенность деталей, настоящая теория должна быть красивой, тупиковая ветвь?, монополисты не только заставляют покупать, но и навязывают свой способ мышления, что бы ты делал без MS, о чем думал, посмотри CLSID в реестре, видел ли я полезный элемент ActiveX, нужно ли бесшовно внедрять что-нибудь во что-нибудь, посмотри Interfaces в реестре, что лучше, Stingray-класс или внедренная по стандарту OLE таблица Excel, тонкий (thin) клиент не будет иметь кода, но будет иметь много картинок и часто покупать дешевые сеансы обслуживания, как раньше билеты в кино или баню, если не поддерживать обратную совместимость, то кто будет покупать, лучше не купить, чем перестать играть в DOS-игры, стройный (slim) клиент, хочешь, еще посчитаю – плати доллар, перестань думать, пора работать.)
Дуальные или интерфейсы диспетчеризации (dispinterfaces) в отличие от тех vtable-интерфейсов, с которыми вы уже знакомы, были разработаны для того, чтобы реализовать позднее связывание (late-binding) клиента с сервером. Инструментальная среда разработки Visual Basic в этом смысле является лидером, так как в ней вы почти без усилий можете создать приложение, способное на этапе выполнения, то есть поздно, получить информацию от объекта и пользоваться методами интерфейсов, информация о которых стала доступной благодаря IDispatch.