Распределенная обработка данных

Контрольная работа - Компьютеры, программирование

Другие контрольные работы по предмету Компьютеры, программирование

онента. После CreateInstance определить IID для интерфейсов. (Для того, чтобы определить IID для IUnknown компоновать с UUID.LIB).

  • Реализация клиента, роль которого выполняет main. Клиент начинает с создания компонента при помощи CreateInstance. CreateInstance возвращает указатель на интерфейс IUnknown компонента. Клиент при помощи QueryInterface запрашивает через интерфейс IUnknown указатель на интерфейс IX компонента. Анологично запросить и IY. Использовать эти указатели для доступа к функциям-членам. Запросить интерфейс IZ. QueryInterface возвращает код ошибки, так как СА не реализует IZ. Далее Клиент запрашивает указатель на интерфейс IY через указатель на интерфейс IX, pIX. Поскольку компонент поддерживает IY, этот запрос будет успешным, и клиент сможет использовать возвращенный указатель на интерфейс IY так же, как он использовал первый указатель. Затем клиент запрашивает интерфейс IUnknown через указатель на IY. Поскольку все интерфейсы COM наследуют IUnknown, этот запрос должен быть успешным, причем возвращенный указатель совпадет с первым указателем, так как . QueryInterface возвращает один и тот же указатель на все запросы к IUnknown.
  • Теоретические сведения:

    В 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