Распределенная обработка данных
Контрольная работа - Компьютеры, программирование
Другие контрольные работы по предмету Компьютеры, программирование
онента. После CreateInstance определить IID для интерфейсов. (Для того, чтобы определить IID для IUnknown компоновать с UUID.LIB).
Теоретические сведения:
В COM клиент взаимодействует с компонентом с помощью интерфейса
IUnknown, который определен в заголовочном файле UNKWN.H:
Interface IUnknown
{
virtual HREZULT --stdcall QueryInterface( const IID&iid,
void * * ppv) = 0 ;
virtual ULONG --stdcall Addref( ) = 0 ;
virtual ULONG --stdcall Release( ) = 0 ;
};
Функцию с именем QueryInterface клиент вызывает, чтобы определить, поддерживает ли компонент некоторый интерфейс. У функции QueryInterface два параметра. Первый параметр идентификатор интерфейса. Второй параметр - адрес, по которому QueryInterface помещает указатель на искомый интерфейс.
QueryInterface возвращает HREZULT 32-разрядный код результата.
QueryInterface может возвратить либо S_OK, либо E_NOINTERFACE. Клиент не должен прямо сравнивать возвращаемое QueryInterface значение с этими константами; для проверки надо использовать макросы SUCCEEDED или FAILED.
Получение указателя на IUnknown
Для получения указателя на IUnknown использовать функцию, например, CreateInstance которая создает компонент и возвращает указатель на IUnknown:
IUnknown * CreateInstance( )
Реализация функции CreateInstance:
IUnknown * pI = static_cast(new CA) ;
PI->Addref( ) ;
Return pI ;
Использование QueryInterface.
Предположим, что у нас есть указатель на IUnknown, pI. Чтобы определить, можно ли использовать некоторый другой интерфейс, мы вызываем QueryInterface, передавая ей идентификатор нужного нам интерфейса. Если QueryInterface отработала успешно, мы можем пользоваться указателем:
void foo(IUnknown* pI)
{
// Определить указатель на интерфейс
IX* pIX=NULL;
// Запросить интерфейс IX
HREZULT hr = pI-> QueryInterface(IID_IX, (void**)&pIX) ;
// Проверить значение результата
if (SUCCEEDED(hr))
{
// Использовать интерфейс
pIXFx( ) ;
}
}
Реализация QueryInterface.
Запишем QueryInterface для следующего компонента, реализуемого классом CA:
Interface IX : IUnknown { /*…*/ } ;
Interface IY : IUnknown { /*…*/ } ;
Class CA : public IX, public IY { /*…*/ } ;
Следующий фрагмент кода реализует QueryInterface для класса, приведенного выше фрагмента кода.
HREZULT --stdcall CA:: QueryInterface( const IID&iid, void * * ppv);
{
if (iid ==IID_IUnknown)
{
// Клиент запрашивает интерфейс IUnknown
*ppv = static_cast(this) ;
}
else if (iid ==IID_IX)
{
// Клиент запрашивает интерфейс IX
*ppv = static_cast(this) ;
}
else if (iid ==IID_IY)
{
// Клиент запрашивает интерфейс IY
*ppv = static_cast(this) ;
}
else
{
// Мы не поддерживаем запрашиваемый клиентом интерфейс.
// Установить возвращаемый указатель в NULL.
*ppv = NULL ;
return E_NOINTERFACE ;
}
static_castAddRef( ) ;
return S_OK ;
}
Текст программы:
#include "stdafx.h"
#include "iostream.h"
#include "objbase.h"
#include "conio.h"
void trace(const char* msg) { cout << msg << endl; }
// Интерфейсы
interface IX : IUnknown
{
virtual void __stdcall Fx() = 0;
};
interface IY : IUnknown
{
virtual void __stdcall Fy() = 0;
};
interface IZ : IUnknown
{
virtual void __stdcall Fz() = 0;
};
// Предварительные объявления GUID
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
//
// Компонент
class CA : public IX, public IY
{
// Реализация IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef() { return 0; }
virtual ULONG __stdcall Release() { return 0; }
// Реализация интерфейса IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
// Реализация интерфейса IY
virtual void __stdcall Fy() { cout << "Fy" << endl; }
};
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
trace("QueryInterface: Vernyt ykazatel na IUnknown");
*ppv = static_cast(this);
}
else if (iid == IID_IX)
{
trace("QueryInterface: Vernyt ykazatel na IX");
*ppv = static_cast(this);
}
else if (iid == IID_IY)
{
trace("QueryInterface: Vernyt ykazatel na IY");
*ppv = static_cast(this);
}
else
{
trace("QueryInterface: Interface No!");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_castAddRef();
return S_OK;
}
// Функция создания
IUnknown* CreateInstance()
{
IUnknown* pI = static_cast(new CA);
pI->AddRef();
return pI;
}
// IID
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IY =
{0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IZ =
{0x32bb8322, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// Клиент
int main()
{
HRESULT hr;
trace("Client: Polychit