1. Понятие распределенной системы 2. Архитектура предприятия 3. Декомпозиция распределенных систем 4. Сетевой клиент 5. Сетевой сервер Вопросы.

Презентация:



Advertisements
Похожие презентации
Фабрики Класса IDL. Создание компонента - 1 // // Функция создания // extern C IUnknown* CreateInstance() { IUnknown* pI = (IUnknown*)(void*)new CA; PI->AddRef();
Advertisements

1 ИССЛЕДОВАНИЕ ВОЗМОЖНОСТЕЙ COM- ТЕХНОЛОГИИ ДЛЯ ПОСТРОЕНИЯ РАСПРЕДЕЛЕННЫХ ПРОГРАММНЫХ ПРОДУКТОВ Component Object Model Министерство образования и науки.
Загруженная в оперативную память программа (ЕХЕ-файл) становится процессом. Процесс - это выполняемая программа, процесс имеет свою память, описатели.
COM (Component Object Model) – модель многокомпонентных объектов.
1 Современные системы программирования. Часть 2. Системное и прикладное программное обеспечение Малышенко Владислав Викторович.
Основы информатики Классы Заикин Олег Сергеевич zaikin.all24.org
ПАРАМЕТРЫ СОКЕТА Методическое пособие по дисциплине «Программное обеспечение компьютерных сетей и информационных систем»
Обработка исключительных ситуаций Исключительная ситуация (исключение) – это ошибка, возникающая во время выполнения программы. Например, ошибка работы.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
WEB- ТЕХНОЛОГИИ Лекция 6. Понятие Web- сервисов 1 Интерфейс в глобальную сеть для некоторого абстрактного программного обеспечения, этот интерфейс позволяет.
Алексей Игнатенко. Независимый программный модуль, обычно подключаемый на этапе выполнения программы.
Система усиленной аутентификации по отпечатку пальца.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Архитектура операционных систем Семестр 2, Лекция 1.
1 Диаграммы реализации (implementation diagrams).
ДонНУ, кафедра КТ, проф.В.К.Толстых WCF-службы Создание и тестирование.dll-библиотеки WCF-служб Из цикла лекций «Internet-технологии разработки приложений»
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
К построению и контролю соблюдения политик безопасности распределенных компьютерных систем на основе механизмов доверия А. А. Иткес В. Б. Савкин Институт.
Архитектура операционных систем. Архитектура ОС Состав модулей (компонент) ОС Структура связей между отдельными модулями ОС Принципы взаимодействия модулей.
Реализация концепции построения и формирования отраслевой системы государственного учета, регистрации и мониторинга (ОСГУРМ) информационных ресурсов сферы.
Транксрипт:

1. Понятие распределенной системы 2. Архитектура предприятия 3. Декомпозиция распределенных систем 4. Сетевой клиент 5. Сетевой сервер Вопросы

Объект+интрефейс Объект и интерфейс Объект инкапсулирует данные, называемые состоянием (state), и операции над этими данными, называемые методами (methods). Доступ к методам можно получить через интерфейс этого объекта. Объект может реализовывать множество интерфейсов. Для данного описания интерфейса может существовать несколько объектов, предоставляющих его реализацию. Разделение объектов и интерфейсов позволяет размещать интерфейс на одну машину при том, что сам объект (компонент) находится на другой.

Организация удаленных объектов (RMI)

Организация удаленных объектов 1. Клиент вызывает процедуру 2. Клиентская заглушка строит сообщение. 3. Сообщение отправляется по сети на сервер. 4. Операционная система сервера передает сообщение серверной заглушке. 5. Серверная заглушка распаковывает сообщение. 6. Серверная заглушка выполняет локальный вызов процедуры

Удаленные объекты Организация удаленных объектов 1.Когда клиент выполняет привязку к распределенному объекту, в адресное пространство клиента загружается реализация интерфейса объекта, называемая заместителем (рroху). 2.Его действия выполнить маршалинг параметров в сообщениях при обращении к методам и демаршалинг данных из ответных сообщений, содержащих результаты обращения к методам, передавая их клиенту. 3.Сами объекты находятся на сервере и предоставляют необходимые клиентской машине интерфейсы.

Удаленные объекты Организация удаленных объектов 4. Входящий запрос на обращение к методу сначала попадает на серверную заглушку, часто именуемую скелетоном {skeleton). 5. Скелетон преобразует его в правильное обращение к методу через интерфейс объекта, находящегося на сервере. Серверная заглушка также отвечает за маршалинг параметров в ответных сообщениях и их пересылку заместителю клиента. 6. Характерной особенностью распределенных объектов является то, что их состояние (данные) не распределяется оно локализовано на одной машине. С других машин доступны только интерфейсы, реализованные в объекте. Такие объекты еще называют удаленными (remote object).

Взаимодействие компонентов Межпроцессное взаимодействие

повторное использование программных компонент Архитектуры компонент

DCOM Преимущества и недостатки DCOM Преимущества Независимость от языка програмирования Динамические и статические вызовы Динамическое нахождение объектов Маштабированность Открытый стандарт (контроль со стороны) Недостатки Сложность реализаций Зависимость от платформы Отсутствие именований через URL Проблемы с безопасностью у ActiveX компонентов

DCOM Преимущества и недостатки RMI Преимущества Быстрота и простота в использовании Java-оптимизация Возможность передачи объектов по значению Мощные механизмы безопасности Недостатки Поддержка одного языка - java Собственный протокол взаимодействия - RMI Проблемы интегрирования с существующим ПО Плохая масштабированность

CORBA Преимущества и недостатки CORBA Преимущества Независимость от платформы Независимость от языка програмирования Динамические вызовы Динамическое знахожения объектов Маштабированность CORBA-сервисы Большая индустриальная поддержка Недостатки Отсутствует передача параметров по значению Отсутствует именование через URL

SOA Service Oriented Architecture Web-сервиси-это технология работы с сообщениями, в которой передача сообщений основана на XML (SOAP), а в качестве траспортного уровня используются сети Internet / Intranet. Описание Web-сервисов осуществляется на языке WSDL - надстройкой над XML

CORBA Преимущества и недостатки SOA Преимущества Независимость от платформы Независимость от языка програмирования Гибкость Маштабированность Открытость стандартов Динамический поиск и подключение модулей Недостатки Ресурсоемкость Недостаточная изученность

Поняття компонентних технологій Анализ технологий

Архитектура СОМ СОМ - component object model Эта технология описывает модель объекта и способы взаимодействия объектов и программ.

СОМ Расширения технологии COM Серверы автоматизации (OLE-автоматизация) - возможность автоматического общения между компонентами COM и приложениями через базовый интерфейс, Активные серверные страницы -файлы имеют расширение.asp. ActiveX-компоненты были первоначально созданы для распространения в Интернете. Представляют собой серверы COM, встраиваемые в приложения и имеющие средства своей визуальной настройки. Контроллеры автоматизации – это клиенты COM, которые управляют серверами автоматизации и имеют дополнительные возможности настройки управления.

СОМ Расширения технологии COM Контроллеры автоматизации – это клиенты COM, которые управляют серверами автоматизации и имеют дополнительные возможности настройки управления. Библиотеки типов – хранят описания объектов и их интерфейсов. Активные документы (например, документы Word) поддерживают технологию OLE, методику перетаскивания и т.п. Визуальные мультипроцессорные объекты – это объекты COM, которые могут использоваться в одновременно выполняющихся процессах. DCOM – распределенная технология COM. Она позволяет создавать COM-объекты, работающие на разных компьютерах в сети.

СОМ Составные части технологии COM Сервер COM – это законченный модуль кода.exe и.dll, где хранится код одного или нескольких компонентов COM. Клиент COM – это программный код, в котором происходит обращение к интерфейсу COM с запросом на выполнение услуг серверов COM. Клиент знает, что надо получить от сервера, но не знает, как это будет реализовано и где сервер находится физически.

СОМ Составные части технологии COM Интерфейс COM описывает методы и свойства, доступные программам, обращающимся к COM-объекту. Объект COM может иметь один или несколько интерфейсов COM и содержит их описание и реализацию. Интерфейс COM позволяет клиентам COM общаться с COM- сервером на основе стандартного механизма публикаций интерфейса, т.е. стандартной регистрации в ОС, после которой изменения интерфейса недопустимы. Это гарантирует одинаковую работу COM-объекта в любых условиях.

СОМ Составные части технологии COM Интерфейс IUnknown поддерживается каждым объектом Он позволяет узнать о наличии других интерфейсов, наследующих его характеристики. Интерфейс в DCOM имеет уникальный 128-битный идентификатор, который называется идентификатором интерфейса (Interface Identifier, IID), Каждый IID абсолютно уникален, не существует двух интерфейсов с одинаковым идентификатором IID GUID помогает избежать проблем при совпадении имен различных объектов. COM-объект может быть реализован на любом языке программирования.

СОМ Составные части технологии COM Сервер COM при обращении получает идентификатор класса Идентификатор класса ClsId представляет собой глобальный идентификатор интерфейса, который ссылается на подходящий COM-объект. Сервер COM создает специальный объект – "фабрику классов", Фабрика классов создает и загружает экземпляр нужного объекта, а также экземпляр специального класса с именем Coclass, Coclass обеспечивает возможность обращения к объекту COM.

Чтобы превратить объект С++ в СОМ-сервер, необходимы следующие действия: Реализовать набор функций, которые определены в спецификации СОМ, т.е. реализовать интерфейс IUnknown. Объект должен иметь идентификатор класса CLSID. Объект должен зарегистрироваться в системном реестре. СОМ Создание СОМ-объекта

Для уникальной идентификации интерфейсов и компонентов (СОМ-серверов) используется GUID (Globally Unique IDentifier -глобальный уникальный идентификатор). Необходимость гарантировать уникальность идентификаторов интерфейса и компонента вызвана: 1. Если два интерфейса имеет одинаковые идентификаторы, то клиент легко может получить от QueryInterface() неверный указатель на интерфейс. 2. Компоненты создаются разработчиками разных стран. При этом разработчики должны быть уверены, что идентификаторы интерфейсов не будут конфликтовать. GUID представляет собой 128 битовое уникальное число. GUID и CLSID Guid+Clsid

Получить его можно одним из следующих способов: 1.Использовать функцию библиотеки СОМ CoCreateGuid(). 2.Использовать программу генерации GUID guidgen.exe, поставляемую вместе с Microsoft Developer's studio. 3.Использовать утилиту uuidgen.exe. 4.Обратиться в Microsoft и получить блок из 256 GUID для собственного использования. Никто из пользователей не получит такой или перекрывающийся набор GUID. Для объявления и определения GUID в программе он присваивается константам или определяется с помощью макроса DEFINE_ GUID, например: // {A888F561-58E4-11d0-A68A E3100} DEFINE_GUID( IID_IMath, 0xa888f561, 0x58e4, 0x11d0, 0xa6, 0x8a, 0x0, 0x0, 0x83, 0x7e, 0x31, 0x0); Guid+Clsid

GUID, использующийся для идентификации компонентов СОМ, называется идентификатором класса и имеет тип CLSID. Два компонента могут реализовать одинаковые наборы интерфейсов, но у них должны быть разные CLSID. Компоненты могут добавлять новые интерфейсы, не изменяя CLSID. Если изменение компонента отражается на работе какого-нибудь приложения, компоненту надо дать новый CLSID. Guid+Clsid CLSID

Реестр Windows - это регистрационная база данных записей операционной системы. Реестр содержит информацию об: аппаратном обеспечении программном обеспечении, конфигурации компьютера пользователях. Клиенты могут искать в реестре нужные компоненты. Системный реестр Windows Реестр Windows

Реестр реализован в виде иерархического структуры, В основе иерархии лежат элементы, называемые ключами. Ключ может включать в себя: набор подключей, набор именованных параметров параметр по умолчанию. : Системный реестр Windows Реестр Windows

В реестре существуют такие первичные или корневые ключи Реестр Windows

СОМ использует раздел HKEY_CLASSES_ROOT. Подразделом HKEY_CLASSES_ROOT является раздел CLSID. В этом разделе перечислены CLSID всех компонентов, установленных в системе. CLSID хранится в Реестре как строка формата: {хххххххх-хххх-хххх-хххх-хххххххххххх}. В каждом разделе CLSID параметр по умолчанию задает "дружественное" имя компонента. В разделе CLSID есть подраздел InProcServer32. Его параметр имя файла DLL это сервер в процессе (in ргос); В разделе CLSID есть подраздел LocalServer32. Его параметр имя файла exe. это локальный сервер, загружается в процесс сервера на другой машине и предоставляет сервисы клиенту. Реестр Windows

Специальные разделы реестра связывают GUID с другими данными, например: AppID Подразделы данного раздела связывают APPID (application ID идентификатор приложения) с именем удаленного сервера. Component Categories - Эта ветвь Реестра связывает CATID (component category ID идентификатор категории компонентов) с соответствующей категорией. Interface Данный раздел связывает IID с информацией, нужной для доступа к интерфейсу "через границы" процессов. Licenses Раздел Licenses хранит лицензии на право использования компонентов СОМ. Реестр Windows

Typelib библиотеки типа содержат информацию о параметрах функций-членов интерфейсов, связывает LIBID с именем файла, в котором хранится библиотека типа. ProgID отображает "дружественную", понятную программисту строку в CLSID. ProgID имеет следующий формат:.. Примеры из Реестра: Visio.Application.3 Visio.Drawing.4 Office.Binder.95 Реестр Windows

СОМ предоставляет библиотеку функций, называемую библиотекой СОМ. Библиотека реализована в ole32.dll, заголовочный файл objbase.h Библиотека СОМ содержит следующие группы функций: фундаментальные функции API, которые облегчают создание приложений COM, клиентов и серверов. Для клиентов СОМ библиотека поставляет основные функции создания объектов; для серверов - средства для их выгрузки; функции определения идентификатора класса, регистрацию серверов в системном реестре; функции дистанционного управления при реализации объекта в локальном или удаленном сервере; функции, позволяющие приложению управлять размещением его в памяти в пределах процесса. Библиотека СОМ

Функция Реализаци я Назначение CoInitializeклиент и сервер Инициализирует сервисы СОМ-библиотеки для использования их в программе. CoInitializeЕхклиент и сервер Инициализирует сервисы СОМ-библиотеки для использования потоковых моделей СОМ. CoUninitializeклиент и сервер Освобождает ресурсы СОМ-библиотеки при отсутствии потребности в них. CoBuildVersionВозвращает номер версии библиотеки СОМ CoCreateGUIDсерверСоздает GUID, уникальное 128-разрядное целое число, используемое для идентификаторов интерфейса и CLSID IsEqualGUIDсерверСравнение двух GUID IsEqualIIDсерверСравнение двух IID IsEqualCLSIDКлиентСравнение двух CLSID CoCreateInstanceКлиентСоздает новый экземпляр СОМ-объекта, ассоциированного с указанным CLSID на локальном сервере.

CoGetClassObjectКлиентСоздает несколько экземпляров объектов, основанных на единственном CLSID. Обращение к фабрике классов для получения экземпляра заданного СОМ-объекта CoRegisterClassObjectсерверРегистрация фабрики классов для определенного СОМ-объекта CoRevokeClassObjectсерверИнформирование СОМ-объекта от недоступности фабрики классов CLSIDFromProgIDсерверПолучение CLSID для заданного программного идентификатора ProgID ProgIDFromCLSIDсерверПолучение программного идентификатора ProgID для заданного CLSID. CoCreateInstanceEx.КлиентСоздает новый экземпляр СОМ-объекта, ассоциированного с указанным CLSID на удаленном сервере.

DllCanUnloadNowсерверСообщает СОМ, поддерживает ли данная Dll какие-либо объекты для определения возможности выгрузки Dll DllRegisterServerсерверРегистрация компонента в системном реестре Windows DllUnregisterServerсерверУдаление информации о компоненте из системного реестраWindows DllGetClassObjectсерверТочка входа Dll для создания фабрики классов

Назначение Фабрики классов 1.Создать экземпляры компонентов по запросу клиента. Фабрики классов и их реализация Фабрика классов

Конкретная фабрика класса создает компоненты, соответствующие только одному конкретному идентификатору класса CLSID. Клиент использует поддерживаемые фабрикой класса интерфейсы для управления созданием компонентов. Стандартный интерфейс создания компонентов IClassFactory. Фабрики классов могут реализовываться в виде отдельных СОМ-объектов с собственными CLSID или могут быть частью самого СОМ-объекта, в которых реализован интерфейс IClassFactory.

Стандартный интерфейс, который поддерживают фабрики класса для создания компонентов, это IClassFactory. Объявление этого интерфейса приводится ниже: interface IClassFactory : public lUnknown { HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) ; HRESULT __stdcall LockServer(BOOL bLock) ; }; Интерфейс IClassFactory Реестр Windows

Метод IClassFactory::Createlnstance() создает экземпляр компонента, т.е. новый СОМ-сервер. Для этого клиент должен получить указатель на IClassFactory и через него вызвать метод Createlnstance() фабрики классов. Первый параметр, pUnknownOuter указатель на интерфейс lUnknown. Второй параметр - это ссылка на требуемый идентификатор интерфейса. Третий параметр - указатель на область памяти, где должен храниться требуемый интерфейсный указатель. С помощью этих параметров вызывающая функция может запросить интерфейс компонента одновременно с созданием последнего. Это экономит клиенту один вызов функции. Если компонент к тому же выполняется на удаленной машине, то так экономится один цикл запроса - ответ по сети. Метод Createlnstance()

IClassFactory::Createlnstance() не получает в качестве параметра CLSID. Это означает, что данная функция может создавать компоненты, соответствующие только одному CLSID. Фабрика класса для данного CLSID создается тем же разработчиком, который реализует соответствующий компонент. Компонент-фабрика класса в большинстве случаев содержится в той же DLL, что и создаваемый компонент. Задача фабрики класса состоит в том, чтобы знать, как создается компонент, и инкапсулировать это знание так, чтобы максимально изолировать клиента от требований компонента.

Является корневым СОМ-интерфейсом, который поддерживаемым всеми другими интерфейсами. Используется для: управления жизненным циклом объекта в памяти; обеспечения доступа клиента ко всем интерфейсам, реализованным в сервере. Интерфейс IUnknown СОМ

1.Реализуя интерфейс IUnknown, обычный объект превращается в СОМ-сервер. 2.Реализация IUnknown - минимальное условие для совместимости с СОМ. 3.Каждый СОМ-сервер реализует IUnknown так, что все они следуют одним и тем же правилам при создании и уничтожении объекта. 4.Все интерфейсы СОМ должны наследовать IUnknown. Возможности IUnknown, СОМ

5. Если у клиента есть указатель на IUnknown, то клиент может запросить через него другие интерфейсы СОМ

Определение IUnknown содержится в заголовочном файле unknwn.h interface IUnknown { public: virtual HRESULT __stdcall QueryInterface(const IID& iid, void *ppv)=0; virtual ULONG _stdcall AddRef(void)=0; virtual ULONG _stdcall Release(void)=0; }; Определение интерфейса IUnknown СОМ

DECLARE_INTERFACE (IUnknown) { STDMETHOD(QueryInterface)(THIS_ IID& iid, LPVOID FAR* ppv)PURE; STDMETHOD_(ULONG, AddRef)PURE; STDMETHOD_(ULONG,Release)PURE; }; Определение IUnknown с помощью макроса: Макрос STDMETHOD() возвращает тип HRESULT, который сообщает об успешном или неуспешном завершении процесса. Макрос STDMETHOD_() возвращает значение типа, указанного в качестве первого параметра. PURE - реализовано как 0 для чисто виртуальных функций. СОМ

Все интерфейсы СОМ наследуют IUnknown и содержат указатели на QueryInterface, Addref, Release в первых трех элементах vtbl pIX Указатель vtbl QueryInterface AddRef Release Fx QueryInterface AddRef Release Fx Release AddRef Таблица виртуальных функций СА СОМ Таблица виртуальных функций

Запрос интерфейса Каждый СОМ-сервер прямо или косвенно порождается от IUnknown. IUnknown поддерживает возможность доступа к другим интерфейсам этого же объекта посредством функции QueryInterface(). Получить указатель на интерфейс IUnknown можно с помощью функции CreateInstance(), которая создает компонент и возвращает указатель на IUnknown QueryInterface

Интерфейсы, которые поддерживают компоненты, определяются указателями, которые возвращает QueryInterface(). Клиент может узнать, какие интерфейсы поддерживает компонент, запросив компонент и указатель на нужный интерфейс. Функция QueryInterface() возвращает указатель на интерфейс, если компонент его поддерживает, в противном случае возвращается код ошибки. Тогда клиент может запросить указатель на другой интерфейс или выгрузить компонент. QueryInterface() QueryInterface

Прототип функции: virtual HRESULT __stdcall QueryInterface( const IID& iid, void *ppv)=0; Параметры: сonst IID& iid – идентификатор интерфейса - GUID void *ppv – адрес, по которому QueryInterface помещает указатель на искомый интерфейс. Возвращаемое значение имеет тип HRESULT разрядный код результата: 0-15 биты содержат код ошибки, биты – тип ошибки, бит 31 – наличие ошибки. QueryInterface() может возвратить значение S_OK и указатель, E_NOINTERFACE и NULL. QueryInterface

HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv) { //параметры: идентификатор запрашиваемого интерфейса, возвращаемый указатель на запрашиваемый интерфейс if (iid == IID_IUnknown) //если запрашиваемый интерфейс IUnknown *ppv = static_cast (this) ; //вернуть указатель на IUnknown else if (iid == IID_IX) //если запрашиваемый интерфейс IX *ppv = static_cast (this) ; //вернуть указатель на интерфейс IX else if (iid == IID_IY) //если запрашиваемый интерфейс IY *ppv = static_cast (this) ; //вернуть указатель на IY else //сервер не поддерживает запрашиваемый клиентом интерфейс { *ppv = NULL ; //установить значение возвращаемого указателя в NULL return E_NOINTERFACE ; //вернуть E_NOINTERFACE типа HRESULT } reinterpret_cast (*ppv)->AddRef() ; // увеличить счетчик ссылок на интерфейсы return S_OK ; //вернуть значение успешного поиска интерфейса } Реализация QueryInterface()

static_cast – оператор стандартного преобразования типов static_cast (this)(IX*)this reinterpret_cast - оператор нестандартного преобразования типов

Использование QueryInterface() void main() { HRESULT hr ; //возвращаемый QueryInterface() код ошибки IUnknown* pIUnknown = CreateInstance() ; //определение указателя на интерфейс IUnknown IX* pIX = NULL ; //установка указателя на требуемый интерфейс, //в NULL для защиты от ошибок hr = pIUnknown ->QueryInterface(IID_IX, (void**)&pIX) ; //запрос интерфейса IX if (SUCCEEDED(hr)) // проверка кода возврата функции // QueryInterface() pIX->Fx(); //если интерфейс найден, то вызов // функции, реализующей интерфейс else cout

Управлять временем жизни полученных интерфейсов можно с помощью функций AddRef() и Release(). AddRef() сообщает компоненту, что клиент будет использовать интерфейс. Release() сообщает компоненту, что клиент использование интерфейса закончено. Управление жизненным циклом компонента AddRef+Release

class CA : public IX, public IY { private: long m_cRef; //счетчик ссылок virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; //увеличение счетчика ссылок virtual ULONG __stdcall Release() ; //уменьшение счетчика ссылок //Реализация интерфейсов компонента ………………………………… public: CA() : m_cRef(0) {} // Constructor ~CA() { trace("CA: Destroy self.") ;} // Destructor } ; Реализация AddRef() и Release() AddRef+Release

ULONG __stdcall CA::AddRef() { return ++m_ cRef; //счетчик ссылок на интерфейсы } /////////////////////////////////////////////////////////////////////////////////////// ULONG __stdcall CA::Release() { if (--m_ cRef ==0) { delete this; return 0; } return m_ cRef; } AddRef+Release

//Вариант реализации функций AddRef() и Release() //с помощью функций Win32 ULONG __stdcall CA::AddRef() { return InterlockedIncrement(&m_cRef) ; } //////////////////////////////////////////////////////////////////////////////////////// ULONG __stdcall CA::Release() { if (InterlockedDecrement(&m_cRef) == 0) {delete this ; return 0 ; } return m_cRef ; } AddRef+Release

//lec2.h #include using namespace std; void trace(const char* msg) { cout

// Компонент class CA : public IX, public IY { // объявление функций IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ; // реализация интерфейса IX virtual void __stdcall Fx() { cout

#include"lec2_2.h" //реализация функции запроса интерфейса HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown) //если задан идентификатор интерфейса IUnknown {trace("CA QI: Return pointer to IUnknown.") ; *ppv = static_cast (this) ;//получить указатель на IUnknown } else if (iid == IID_IX)//если задан идентификаторинтерфейса IX {trace("CA QI: Return pointer to IX.") ; *ppv = static_cast (this) ;//получить указатель на IX } else if (iid == IID_IY)//если задан идентификатор интерфейса IY {trace("CA QI: Return pointer to IY.") ; *ppv = static_cast (this) ;// получить указатель на IY } else//если не найден указатель на нужный интерфейс {trace("CA QI: Interface not supported.") ; *ppv = NULL ; return E_NOINTERFACE; //вернуть код ошибки } reinterpret_cast (*ppv)->AddRef() ; // увеличить счетчик ссылок return S_OK ; //вернуть код успешного завершения }

//реализация функций подсчета ссылок ULONG __stdcall CA::AddRef() { cout

// IIDs //идентификаторы интерфейсов IIDs // {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}} ;

// Client int main() { HRESULT hr ; trace("Client: Get an IUnknown pointer.") ; IUnknown* pIUnknown = CreateInstance() ; trace("Client: Get interface IX.") ; IX* pIX = NULL ; hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX) ; if (SUCCEEDED(hr)) { trace("Client: Succeeded getting IX.") ; pIX->Fx() ; // Use interface IX. pIX->Release() ; } trace("Client: Get interface IY.") ; IY* pIY = NULL ; hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY) ; if (SUCCEEDED(hr)) { trace("Client: Succeeded getting IY.") ; pIY->Fy() ; // Use interface IY. pIY->Release() ; }

trace("Client: Ask for an unsupported interface.") ; IZ* pIZ = NULL ; hr = pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ) ; if (SUCCEEDED(hr)) { trace("Client: Succeeded in getting interface IZ.") ; pIZ->Fz() ; pIZ->Release() ; } else { trace("Client: Could not get interface IZ.") ; } trace("Client: Release IUnknown interface.") ; pIUnknown->Release() ; return 0; }