Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Добавление методов интерфейса



До сих пор рассматривались только функциональные возможности, обеспечиваемые средствами ATL. Сейчас мы опишем конкретные функциональные возможности создаваемого нами компонента. для этого с помощью мастера объектов в проект сервера будут добавлены два новых файла МАТН.СРР и МАТН.Н, а также сделаны изменения в IDL-файле компонента, которые мы вскоре рассмотрим. Прежде всего, в новый класс следует добавить четыре метода.

class ATL_NO_VTABLE CMath: public CComObjectRootEx< CComSingleThreadModel>, public CComCoClass< CMath, & CLSID_MathComponent>, public IDispatchImpl< IMath, & IID_IMath, & LIBID_AUTOSVRLib> {public: CMath() { } DECLARE_REGISTRY_RESOURCEID(IDR_MATH) BEGIN_COM_MAP(CMath) COM_INTERFACE_ENTRY(IMath) COM_INTERFACE_ENTRY(IDispatch)END_COM_MAP() // IMathpublic: STDMETHOD(Add)( long, long, long* ); STDMETHOD(Subtract)( long, long, long* ); STDMETHOD(Multiply)( long, long, long* ); STDMETHOD(Divide)( long, long, long* ); };

 

Все это вам должно быть уже известно. Сейчас мы просто добавили в объявление класса объявления простых математических функций Приведем реализацию этих функций в файле МАТН.СРР, которая практически не отличается от предыдущей:

STDMETHODIMP CMath:: Add( long op1, long op2, long* pResult ){ *pResult = op1 + op2; return S_OK; } STDMETHODIMP CMath:: Subtract( long op1, long op2, long* pResult ){ *pResult = op1 - op2; return S_OK; } STDMETHODIMP CMath:: Multiply( long op1, long op2, long* pResult ){ *pResult = op1 * op2; return S_OK; } STDMETHODIMP CMath:: Divide( long op1, long op2, long* pResult ){ *pResult = op1 / op2; return S_OK; }

 

Информация о типах

В рассмотренном ранее математическом примере любой клиент, желавший воспользоваться сервисами компонента, нуждался в некоторых предварительных сведениях об интерфейсе этого компонента. Информация о поддерживаемых интерфейсом возможностях, параметрах каждого метода и т.п. должна была быть получена из файла заголовков IMATH.H. Однако СОМ предоставляет и более универсальную технологию обеспечения клиентов подобной информацией. Она реализуется путем представления информации о типах.

Файл, содержащий информацию о типах компонента, создается с помощью языка определения интерфейса (Interface Definition Language — IDL). При создании хранилища компонента с помощью ATL создается также специальный IDL-файл, содержащий информацию о типах для каждого компонента, помещенного в хранилище. Содержимое этого файла преобразуется IDL-компилятором (MIDL.EXE) в двоичный формат и записывается в файл с расширением TLB, который называется библиотека типов. После компиляции информации о типах она должна быть помещена вместе с компонентом либо в самом хранилище, либо в виде отдельного TLB-файла. Способ размещения информации о типах компонента для приложений клиента или компонентных броузеров описывается в разделе ТуреLib реестра.

 

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

В основе языка определения интерфейса фирмы Microsoft лежит спецификация DCE RPC. В общем случае IDL используется для описания интерфейсов удаленного вызова процедур, но фирма расширила спецификацию, включив в этот язык поддержку для СОМ-интерфейсов. Одной из задач IDL, по крайней мере, в контексте СОМ-компонента, является определение интерфейса последнего (т.е. его методов и параметров) независимо от языка программирования. Такое определение затем может быть использовано клиентами компонентов. Поскольку язык IDL позволяет описывать интерфейсы RPC, то он может предоставить для интерфейса компонента и соответствующую программу транспортировки, что дает возможность обходить межзадачные и сетевые ограничения.

Синтаксис IDL аналогичен синтаксису языка С. Таким образом, определение интерфейса компонента очень напоминает объявление С++-класса. В IDL не предусмотрены такие типы данных, как структуры, перечисления и т.д. Рассмотрим только основные элементы этого языка, необходимые для построения примера. Ниже приводится программа файла AUTOSV.IDL. Добавьте к файлу выделенные строки.

//// AutoSvr.idl: IDL source for AutoSvr.dll// // This file will be processed by the MIDL tool to// produce the type library (AutoSvr.tlb) and marshalling code. import " oaidl.idl"; import " ocidl.idl"; [ object, uuid(8C30BC10-B8F2-11D0-A756-B04A12000000), dual, helpstring(" IMath Interface" ), pointer_default(unique) ] interface IMath: IDispatch { HRESULT Add( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Subtract( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Multiply( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Divide( [in] long, [in] long, [out, retval] long* pResult ); }; [ uuid(8C30BC01-B8F2-11D0-A756-B04A12000000), version(1.0), helpstring(" AutoSvr 1.0 Type Library" )]library AUTOSVRLib{ importlib(" stdole32.tlb" ); importlib(" stdole2.tlb" ); [ uuid(8C30BC11-B8F2-11D0-A756-B04A12000000), helpstring(" Math Class" ) ] coclass MathComponent { [default] interface IMath; }; };

 

В первой части программы определяется двунаправленный интерфейс IMath. IDL-определениям предшествует блок атрибутов, заключенный в квадратные скобки ([ ]), Данные атрибуты обеспечивают добавочную информацию к последующим определениям. Определение интерфейса IMath начинается несколькими строками атрибутов:

[ object, uuid(8C30BC10-B8F2-11D0-A756-B04A12000000), dual, helpstring(" IMath Interface" ), pointer_default(unique)]

 

Атрибут объекта задает СОМ-, а не RPC-интерфейс. Затем ключевое слово uuid задает GUID интерфейса. Ключевое слово dual обозначает, что интерфейс предоставляет как пользовательский интерфейс с виртуальной таблицей, так и стандартный интерфейс автоматизации IDispatch. Ключевое слово helpstring определяет текст, который может быть отображен броузером объекта. Атрибут POINTER_DEFAULT устанавливает атрибут по умолчанию для всех указателей, определенных в интерфейсе. Далее следует определение интерфейса.

interface IMath: IDispatch{HRESULT Add( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Subtract( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Multiply( [in] long, [in] long, [out, retval] long* pResult ); HRESULT Divide( [in] long, [in] long, [out, retval] long* pResult ); };

 

Данный фрагмент описывает СОМ-интерфейс компонента. Это практически полностью соответствует объявлению С++-класса, использованному ранее. Основное отличие состоит в перечислении параметров. В IDL существует несколько ключевых слов, применимых к параметрам метода. Ключевые слова in и out определяют направленность параметров (т.е. входные они или выходные). Таким образом, СОМ снабжается информацией, необходимой для повышения эффективности процесса транспортировки параметров. Ключевое слово retval определяет тот факт, что параметр должен трактоваться как тип значения, возвращаемого методом. Это играет роль при определении интерфейса для нашего элемента. Остальные строки IDL файла касаются хранилища и сохраняемых в нем объектов.

library AUTOSVRLib{ importlib(" stdole32.tlb" ); importlib(" stdole2.tlb" ); [ uuid(8C30BC11-B8F2-11D0-A756-B04A12000000), helpstring(" Math Class" ) ] coclass MathComponent { [default] interface IMath; }; };

 

Последний блок атрибутов описывает библиотеку типов в целом. В нем содержится информация о GUID, версии и строке помощи, которая используется приложениями поиска компонентов. Ключевое слово library задает имя библиотеки, а последующий блок, как правило, включает все определения, касающиеся конкретного хранилища. В этот блок входит информация о модуле интерфейса, типе и определении компонента. В рассматриваемом примере сервер содержит только компонент Math, заданный ключевым словом coclass. Функция ключевого слова coclass состоит в определении, отдельных компонентов и поддерживаемых ими интерфейсов. Компонент Math предоставляет двунаправленный интерфейс IMath, который принимается по умолчанию. В табл. 14 приводятся основные ключевые слова IDL и их краткое описание.

Таблица 14. Основные ключевые слова IDL

Ключевое слово Описание
Object Является начальным ключевым словом в определении пользовательского интерфейса. За ним следуют несколько атрибутов, описывающих дополнительные возможности интерфейса.
Uuid GUID, однозначно определяющий заданный интерфейс, библиотеку типов или компонентный объект.
Dual Указывает на двунаправленность интерфейса. Двунаправленный интерфейс предоставляет как интерфейс с виртуальной таблицей, так и IDispatch-интерфейс. Все методы двунаправленного интерфейса должны возвращать HRESULT, но могут для определения возвращаемого значения использовать также ключевое слово retval.
Helpstring Задает строку, которая может отображаться на экране средствами просмотра компонента и интерфейса.
Interface Задает фактическое имя интерфейса, которое затем используется в блоке coclass для определения поддерживаемых компонентом интерфейсов.
Coclass Описывает интерфейсы, поддерживаемые в данном СОМ-объекте. GUID идентифицирует компонент в целом.
Default Задает интерфейс компонента по умолчанию. Компонентный объект может иметь максимум два интерфейса по умолчанию — один в качестве исходного передающего интерфейса, а второй — в качестве принимающего.
in/out/retval В вызовах методов это ключевое слово определяет направленность каждого параметра (т.е. входной он или выходной). Ключевое слово retval описывает параметр, который должен трактоваться как возвращаемое значение метода.

 

Создание сервера

Теперь мы полностью подготовлены к созданию проекта сервера. Благодаря ATL нам остается добавить лишь небольшие количество строк программы по сравнению с примером, написанным на C++. ATL предоставляет основное место хранения, счетчик обращений, фабрику классов и поддержку саморегистрации. Все это в предыдущем примере нам приходилось реализовывать самостоятельно.

Для быстрого тестирования компонента AutoSvr можно запустить утилиту OLEVIEW, установить для нee режим Expert Mode и открыть раздел Automation Objects. Компонент получит строковое имя Math Class. Откройте в дереве узел класса Math, и утилита OLEVIEW попытается загрузить компонент. Если все пойдет нормально, то на экране появятся имена трех поддерживаемых компонентом интерфейсов.


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-04-11; Просмотров: 838; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.012 с.)
Главная | Случайная страница | Обратная связь