Программирование >>  Арифметические и логические операции 

1 ... 29 30 31 [ 32 ] 33 34 35 ... 53


ставляющих собой обёртки выбранных нами интерфейсов. К сожалению, ClassWizard не генерирует константы, перечисленные в библиотеке типов, игнорирует некоторые интерфейсы, добавляет к именам свойств префиксы Put и Get и не отслеживает ссылок на другие библиотеки типов.

Второй - CComDispatchDriver является частью библиотеки ATL. В VC нет средств, которые могли бы облегчить работу с этим классом, но у него есть одна особенность - с его помощью можно вызывать методы и свойства объекта не только по ID, но и по их именам, то есть использовать позднее связывание в полном объёме.

Третий набор классов - это результат работы директивы #import.

Последний способ доступа к объектам OLE Automation является наиболее предпочтительным, так как предоставляет достаточно полный и довольно удобный набор классов.

Рассмотрим пример.

Создадим IDL-файл, описывающий библиотеку типов. Наш пример будет содержать описание одного перечисляемого типа SamplType и описание одного объекта ISamplObject, который в свою очередь будет содержать одно свойство Prop и один метод Method.

import oaidl.idl ; import ocidl.idl ;

uuid(37A3AD11-F9CC-11D3-8D3C-0000E8D9FD76),

version(1.0),

helpstring( Sampl 1.0 Type Library )

library SAMPLLib

importlib( stdole32.tlb ); importlib( stdole2.tlb );

typedef enum {

SamplType1 = 1,

SamplType2 = 2 } SamplType;

object,

uuid(37A3AD1D-F9CC-11D3-8D3C-0000E8D9FD76),

dual,

helpstring( ISamplOb]ect Interface ), pointer default(unique)

interface ISamplObject : IDispatch

[propget, id(1)] HRESULT Prop([out, retval] SamplType *pVal); [propput, id(1)] HRESULT Prop([in] SamplType newVal); [id(2)] HRESULT Method([in] VARIANT Var,[in] BSTR Str,[out, retval] ISamplObject** Obj);

uuid(37A3AD1E-F9CC-11D3-8D3C-0000E8D9FD76),

helpstring( SamplObject Class )

coclass SamplObject

[default] interface ISamplObject;

После подключения соответствующей библиотеки типов с помощью директивы #import будут созданы два файла, которые генерируются в выходном каталоге проекта. Это файл sampl.tlh, содержащий описание классов, и файл sampl.tli, который содержит реализацию членов классов. Эти файлы будут включены в проект автоматически. Ниже приведено содержимое этих файлов.

#pragma once

#pragma pack(push, 8)

#include <comdef.h>

namespace SAMPLLib {

Forward references and typedefs struct declspec

(uuid( 37a3ad1d-f9cc-11d3-8d3c-0000e8d9fd76 )) /* dual interface */ ISamplObject; struct /* coclass */ SamplObject;

Smart pointer typedef declarations COM SMARTPTR TYPEDEF (ISamplObject, uuidof(ISamplObject));

Type library items



enum SamplType

SamplTypel = 1, SamplType2 = 2

struct declspec(uuid( 37a3ad1d-f9cc-11d3-8d3c-0000e8d9fd76 ))

ISamplObject : IDispatch {

Property data

declspec(property(get=GetProp,put=PutProp)) enum SamplType

Prop;

Wrapper methods for error-handling

enum SamplType GetProp ( );

void PutProp (enum SamplType pVal );

ISamplObjectPtr Method (const variant t & Var, bstr t Str ); Raw methods provided by interface

virtual HRESULT stdcall get Prop (enum SamplType * pVal) = 0 ;

virtual HRESULT stdcall put Prop (enum SamplType pVal) = 0 ;

virtual HRESULT stdcall raw Method (VARIANT Var,BSTR

Str,struct ISamplObject** Obj) = 0 ; };

struct declspec(uuid( 37a3ad1e-f9cc-11d3-8d3c-0000e8d9fd76 ))

SamplObject;

#include debug\sampl.tli } namespace SAMPLLib #pragma pack(pop) #pragma once

interface ISamplObject wrapper method implementations

inline enum SamplType ISamplObject::GetProp ( ) { enum SamplType result; HRESULT hr = get Prop(& result);

if (FAILED( hr)) com issue errorex( hr, this, uuidof(this));

return result;

inline void ISamplObject::PutProp ( enum SamplType pVal ) { HRESULT hr = put Prop(pVal);

if (FAILED( hr)) com issue errorex( hr, this, uuidof(this));

inline ISamplObjectPtr ISamplObject::Method ( const variant t & Var, bstr t Str ) {

struct ISamplObject * result;

HRESULT hr = raw Method(Var, Str, & result);

if (FAILED( hr)) com issue errorex( hr, this, uuidof(this));

return ISamplObjectPtr( result, false);

Первое на что следует обратить внимание - это на строчку файла sampl.tlh:

namespace SAMPLLib {

Это означает, что компилятор помещает описание классов в отдельное пространство имён, соответствующее имени библиотеки типов. Это является необходимым при использовании нескольких библиотек типов с одинаковыми именами классов, такими, например, как IDocument. При желании, имя пространства имён можно изменить или запретить его генерацию совсем:

#import sampl.dll rename namespace( NewNameSAMPLLib ) #import sampl.dll no namespace

Теперь рассмотрим объявление метода Method:

ISamplObjectPtr Method (const variant t & Var, bstr t Str); Здесь мы видим использование компилятором классов поддержки COM. К таким классам относятся следующие.

♦ com error. Этот класс используется для обработки исключительных ситуаций, генерируемых библиотекой типов или каким либо другим классом поддержки (например, класс variant t будет генерировать это исключение, если не сможет произвести преобразование типов).

♦ com ptr t. Этот класс определяет гибкий указатель для использования с интерфейсами COM и применяется при создании и уничтожении объектов.



♦ variant t. Инкапсулирует тип данных VARIANT и может значительно упростить код приложения, поскольку работа с данными VARIANT напрямую является несколько трудоёмкой.

♦ bstr t. Инкапсулирует тип данных BSTR. Этот класс обеспечивает встроенную обработку процедур распределения и освобождения ресурсов, а также других операций.

Нам осталось уточнить природу класса ISamplObjectPtr. Мы уже говорили о классе com ptr t. Он используется для реализации smart-указателей на интерфейсы COM. Мы будем часто использовать этот класс, но не будем делать этого напрямую. Директива #import самостоятельно генерирует определение smart-указателей. В нашем примере это сделано следующим образом.

Smart pointer typedef declarations

COM SMARTPTR TYPEDEF(ISamplObject, uuidof(ISamplObject));

Это объявление эквивалентно следующему:

typedef com ptr t<ISamplObject,& uuidof(ISamplObject)> ISamplObjectPtr

Использование smart-указателей позволяет не думать о счётчиках ссылок на объекты COM, т.к. методы AddRef и Release интерфейса IUnknown вызываются автоматически в перегруженных операторах класса com ptr t.

Помимо прочих, этот класс имеет следующий перегруженный оператор:

Interface* operator->() const throw( com error); где Interface - тип интерфейса, в нашем случае - это ISamplObject. Таким образом, мы сможем обращаться к свойствам и методам нашего COM объекта. Вот как будет выглядеть пример использования директивы #import для нашего примера:

#import sampl.dll

void SamplFunc () SAMPLLib::ISamplObjectPtr obj;

obj.CreateInstance(L SAMPLLib.SamplObject ); SAMPLLib::ISamplObjectPtr obj2 = obj->Method(1l,L 12345 );

obj->Prop = SAMPLLib::SamplType2; obj2->Prop = obj->Prop;

Как видно из примера создавать объекты COM с использованием классов, сгенерированных директивой #import, достаточно просто. Во-первых, необходимо объявить smart-указатель на тип создаваемого объекта. После этого для создания экземпляра нужно вызвать метод CreateInstance класса com ptr t, как показано в следующих примерах:

SAMPLLib::ISamplObjectPtr obj;

obj.CreateInstance(L SAMPLLib.SamplObject );

obj.CreateInstance( uuidof(SamplObject));

Можно упростить этот процесс, передавая идентификатор класса в конструктор указателя:

SAMPLLib::ISamplObjectPtr obj(L SAMPLLib.SamplObject );

SAMPLLib::ISamplObjectPtr obj( uuidof(SamplObject));

Прежде чем перейти к примерам, нам необходимо рассмотреть обработку исключительных ситуаций. Как говорилось ранее, директива #import использует для генерации исключительных ситуаций класс com error. Этот класс инкапсулирует генерируемые значения HRESULT, а также поддерживает работу с интерфейсом IErrorInfo для получения более подробной информации об ошибке. Внесём соответствующие изменения в наш пример:

#import sampl.dll

void SamplFunc () try {

using namespace SAMPLLib;

ISamplObjectPtr obj(L SAMPLLib.SamplObject );

ISamplObjectPtr obj2 = obj->Metod(1l,L 12345 );

obj->Prop = SAMPLLib::SamplType2;

obj2->Prop = obj->Prop; } catch ( com error& er) {

printf( com error:\n Error : %08lX\n ErrorMessage: %s\n Description : %s\n Source : %s\n , er.Error(),

(LPCTSTR) bstr t(er.ErrorMessage()),

(LPCTSTR) bstr t(er.Description()),

(LPCTSTR) bstr t(er.Source()));



1 ... 29 30 31 [ 32 ] 33 34 35 ... 53

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика