Читаем Сущность технологии СОМ. Библиотека программиста полностью

ISurfboardUser *m_pSurfer;

// to deal with identity relationship of IConnectionPoint,

// define an IShutdownNotify-specific nested class + member

// для работы с отношением тождественности

// IConnectionPoint, определяем специфический для

// IShutdownNotify вложенный класс+член

class XCPShutdownNotify : public IConnectionPoint {

Surfboard *This(void);

// use fixed offset

// испопьзуем постоянное смещение

// IUnknown methods...

// методы IUnknown...

// IConnectionPoint methods...

// методы IConnectionPoint...

} m_xcpShutdownNotify;

// define an ISurfboardUser-specific nested class + member

// определяем специфический для IShutdownNotify вложенный класс+член

class XCPSurfboardUser : public IConnectionPoint {

Surfboard *This(void);

// use fixed offset

// используем постоянное смещение

// IUnknown methods...

// методы IUnknown...

// IConnectionPoint methods...

// методы IConnectionPoint...

} m_xcpSurfboardUser;

// IUnknown methods...

// методы IUnknown...

// ISurfboard methods...

// методы ISurfboard...

// IHazardousDevice methods...

// методы IHazardousDevice...

// ISharkBait methods...

// методы ISharkBait...

// IConnectionPointContainer methods...

// методы IConnectionPointContainer...

};

Следует указать, что экземпляры класса Surfboard будут иметь две отдельные реализации IConnectionPoint, одна из которых используется для присоединения интерфейсов обратного вызова IShutdownNotify, а вторая – для присоединения интерфейсов ISurfboardUser. Эти две реализации разделены на отдельные классы C++, что позволяет каждой реализации IConnectionPoint иметь свои собственные уникальные реализации IUnknown и IConnectionPoint. В частности, может иметься три отдельных реализации QueryInterface со своими собственными наборами интерфейсных указателей, которые могут быть выделены для создания трех отдельных СОМ-копий.

Из приведенного выше определения класса следует такая QueryInterface-peaлизация основного класса Surfboard:

STDMETHODIMP Surfboard::QueryInterface(REFIID riid, void**ppv)

{

if (riid == IID_IUnknown || riid == IID_ISurfboard)

*ppv = static_cast(this);

else if (riid == IID_IHazardousDevice)

*ppv = static_cast< IHazardousDevice *>(this);

else if (riid == IID_ISharkBait)

*ppv = static_cast(this);

else if (riid == IID_IConnectionPointContainer)

*ppv = static_cast(this);

else

return (*ppv = 0), E_NOINTERFACE;

((IUnknown*)*ppv)->AddRef();

return S_OK;

}

Отметим, что доступ к интерфейсу IConnectionPoint не может быть осуществлен через эту главную реализацию QueryInterface. Каждый из методов QueryInterface вложенного класса будет выглядеть примерно так:

STDMETHODIMP Surfboard::XCPShutdownNotify::QueryInterface(REFIID riid, void**ppv)

{

if (riid == IID_IUnknown || riid == IID_IConnectionPoint)

*ppv = static_cast(this);

else

return (*ppv = 0), E_NOINTERFACE;

((IUnknown*)*ppv)->AddRef();

return S_OK;

}

Эту же реализацию можно было бы применить и к классу XCPSurfboardUser. Между объектом Surfboard и двумя подобъектами, которые реализуют интерфейс IConnectionPoint не существует идентичности.

Для того чтобы объект Surfboard не уничтожил себя раньше времени, подобъекты администратора соединений просто делегируют вызовы своих методов AddRef и Release в содержащий их объект surfboard:

STDMETHODIMP_(ULONG) Surfboard::XCPShutdownNotify::AddRef(void)

{

return This()->AddRef();

/* AddRef containing object */

/* AddRef объекта-контейнера */

}

STDMETHODIMP_(ULONG) Surfboard::XCPShutdownNotify::Release(void)

{

return This()->Release();

/* Release containing object */

/* Release объекта-контейнера */

}

В приведенных выше методах предполагается, что метод This возвращает указатель на объект-контейнер Surfboard, используя вычисление некоторого постоянного смещения.

Клиенты находят интерфейсы объекта IConnectionPoint посредством вызова метода объекта FindConnectionPoint, который для класса Surfboard мог бы выглядеть примерно так:

STDMETHODIMP Surfboard::FindConnectionPoint(REFIID riid, IConnectionPoint **ppcp)

{

if (riid == IID_IShutdownNotify)

*ppcp = IID_IShutdownNotify;

else if (riid == IID_ISurfboardUser)

*ppcp = &m_xcpSurfboardUser;

else

return (*ppcp = 0), CONNECT_E_NOCONNECTION;

(*ppcp)->AddRef();

return S_OK;

}

Отметим, что объект выдает интерфейсные указатели IConnectionPoint только при запросе тех интерфейсов, на которые он сможет сделать обратный запрос. Необходимо указать также на поразительное сходство с большинством реализации QueryInterface. Основное различие состоит в том, что QueryInterface имеет дело с импортируемыми (inbound) интерфейсами, в то время как FindConnectionPoint – с экспортируемыми (outbound) интерфейсами.

Поскольку метод IConnectionPoint::Advise принимает только интерфейс IUnknown, статически типизированный как интерфейсный указатель обратного вызова[1], то реализации Advise должны использовать QueryInterface для того, чтобы привязать указатель обратного вызова к соответствующему типу интерфейса:

STDMETHODIMP Surfboard::XCPShutdownNotify::Advise(IUnknown *pUnk, DWORD *pdwCookie)

{

assert (pdwCookie && pUnk);

*pdwCookie = 0;

if (This()->m_pShutdownNotify) // already have one

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Язык программирования Euphoria. Справочное руководство
Язык программирования Euphoria. Справочное руководство

Euphoria (юфо'ри, также рус. эйфори'я, ра'дость) — язык программирования, созданный Робертом Крейгом (Rapid Deployment Software) в Канаде, Торонто. Название Euphoria — это акроним для «End-User Programming with Hierarchical Objects for Robust Interpreted Applications».Euphoria — интерпретируемый императивный язык высокого уровня общего назначения. C помощью транслятора из исходного кода на Euphoria может быть сгенерирован исходный код на языке Си, который в свою очередь может быть скомпилирован в исполнияемый файл или динамическую библиотеку при помощи таких компиляторов, как GCC, OpenWatcom и др. Программа Euphoria также может быть «связана» с интерпретатором для получения самостоятельного исполняемого файла. Поддерживается несколько GUI-библиотек, включая Win32lib и оберток для wxWidgets, GTK+ и IUP. Euphoria имеет встроенную простую систему баз данных и обертки для работы с другими типам баз данных.[Материал из Википедии]

Коллектив авторов

Программирование, программы, базы данных