Модель программирования Component Object Model. Разработка COM-сервера, страница 23

При открытом окне диалога Insert Control вы можете просто ввести букву O — начальную букву нашего элемента OpenGL. Теперь, используя клавиши навигации по списку (стрелки), вы быстро найдете в нем строку OpenGL Class. Выберите ее и нажмите OK. Вы должны увидеть окно внедренного элемента, которое выглядит так, как показано на рисунке.

Стартовая заготовка элемента ActiveX в окне тестового контейнера

Когда клиент COM-объекта пользуется услугами локального или удаленного сервера (то есть когда данные передаются через границы различных процессов или между узлами сети), требуется поддержка маршалинга (marshaling). Так называется процесс упаковки и посылки параметров, передавемых методам интерфейсов, через границы потоков или процессов, который мы слегка затронули ранее. Вы помните, что MIDL генерирует код на языке С для двух компонент: Proxy (представитель COM-объекта на стороне клиента) и Stub (заглушка на стороне COM-сервера).

Эти компоненты общаются между собой и решают проблемы Вавилонской башни, то есть преодолевают сложности обмена данными, возникающие из-за того, что клиент и сервер используют различные типы данных (разговаривают на разных языках). Поистине, чтобы увидеть проблему, надо ее создать.

Интересно то, что при объяснении необходимости этого чудовищного сооружения из:

¨  idl-файла,

¨  кода заглушек (proxy и stub) в вашем рабочем пространстве (см. файлы в папке ATLGLPS),

¨  структуры VARIANT, которую надо использовать (или просто иметь в виду), приводится соображение о том, что программы на разных языках программирования смогут общаться, то есть обмениваться данными. Как мы уже обсуждали, разработчики имеют в виду четыре COM-совместимых языка, два из которых реально используются (Visual C++ и Visual Basic), а два других (VBScrit и Visual J++) едва подают признаки жизни. Здесь надо учесть бурно развивающийся язык C#, который тоже поддерживает движение COM, но не рекомендует создавать новые компоненты в старом (тем, которым мы сейчас пользуемся) стиле.

Откройте и проанализируйте код файла ATLGL.idl. Постарайтесь вникнуть в смысл описаний. Прежде всего отметьте, что в библиотеке типов (library ATLGLLib), сопровождающей COM-объект, появилось описание COM-класса, который предоставляет своим пользователям два интерфейса.

coclass OpenGL

{

[default] interface IOpenGL;

[default, source] dispinterface _IOpenGLEvents;

};

Предшествующий классу блок описаний в квадратных скобках носит вспомогательный характер, поэтому я не привел его здесь. Элементы ActiveX используют события (events) для того, чтобы уведомить приложение-контейнер об изменениях в состоянии объекта в результате действий пользователя. Найдите описание одного из объявленных интерфейсов:

dispinterface _IOpenGLEvents

{

properties:

methods:

};

Пока пустые секции properties: и methods: намекают на то, что мы должны приложить усилия для того, чтобы ввести (с помощью инструментов студии) в разрабатываемый COM-объект способность общения с клиентом. Этот дуальный интерфейс появился потому, что мы (в момент создания COM-объекта) задали поддержку Connection Points.

Информация о втором интерфейсе расположена вне блока, описывающего библиотеку типов:

interface IOpenGL : IDispatch

{

[propput, id(DISPID_FILLCOLOR)]

HRESULT FillColor([in]OLE_COLOR clr);

[propget, id(DISPID_FILLCOLOR)]

HRESULT FillColor([out, retval]OLE_COLOR* pclr);

};

Интерфейс IOpenGL предоставляет своим пользователям двойной (dual) интерфейс. Эта штука опять понадобилось для того, чтобы VBScrit-сценарий мог использовать COM-объекты, созданные с помощью Visual C++. Клиенты, созданные на языке С++, могут (с помощью QueryInterface) получить адрес интерфейса и вызывать его методы, пользуясь таблицей виртуальных функций (vtable), например:

p->SomeMethod(i, d);