developing.ru - клуб программистов Здесь может быть и ваша реклама.
developing.ru >технология COM >
Михаил Безверхов
aspid@developing.ru

COM - от каменного века к бронзовому

Наше изложение, как и сама эволюция, - не стоит на месте. Мы с вами добрались до того места в изложении, когда в самый раз написать второй пример, иллюстрирующий наш подход. И мы его напишем.

Я сразу хочу сказать - я не сторонник больших и универсальных примеров. Пример должен быть настолько краток, чтобы демонстрировать именно то, для чего он написан и ничего больше. Поэтому мы с вами возьмем предыдущий пример и исправим обнаруженные в нём недостатки тем самым программным механизмом, который мы только что изучили во всех промежуточных между этими двумя примерами статьях. Я напомню - прошлый пример страдал двумя фундаментальными недостатками: 1)он делал объекты, но не позволял их уничтожать, когда надобность в них исчезает; 2)он не позволял на стороне клиента "знать" что же за указатель мы получили. И если объект реализовывал более одного интерфейса, то это обстоятельство здорово сковывало свободу клиента - в "обычном попроектном программировании" клиент мог с указателем делать значительно больше.

Исправим пример. Ход исправления - сделаем наш интерфейс NeoInterface наследником системно определенного интерфейса IUnknown. Напишем реализацию методов интрефейса IUnknown в составе наших объектов, а реализацию "полезных" методов трогать не будем - мы только их оформим "как положено" - с возвратом типа HRESULT.

Мы не будем трогать и конструкцию COM-сервера, удовлетворимся на этот раз тем, что "тот" сервер работал. Как должен выглядеть "настоящий COM-сервер", наверное, будет примером №3.

Мы перепишем клиент: наша задача в данный раз - показать как функционирует объект "под управлением IUnknown", а не то, что концептуальная схема "вообще работоспособна". Поэтому мы изменим окно главного диалога - оно теперь не будет вызывать методы двух объектов CBanzai и CHello, а будет порождать отдельные окна - графические объекты. Эти графические объекты будут относительно самостоятельны - при их создании "родительское окно" снабдит их указателем на интерфейс соответствующего объекта, и уже "маленькие окна" будут вызывать методы объектов сервера. Маленьких окон можно породить много - они немодальны, поэтому методы объектов сервера, сцепленных с окном, можно вызывать в произвольном порядке и наблюдать за их поведением в разных ситуациях. Я обращаю внимание - в данном случае вы будете вызывать методы уже настоящихCOM-объектов.

Исходные проекты этого примера находятся здесь. С ними нужно поступить так же, как и с проектами предыдущего примера - собрать, и скопировать исполняемые модули в один каталог.

Для тестирования запустите EXE. Программа покажет диалог с тремя кнопками - "Создать Banzai", "Создать Hello", "Закрыть панель". Кнопка "Закрыть панель" завершает весь процесс. Кнопки "Создать..." создают новое "маленькое окно" и получают у сервера новый экземпляр указателя на COM-интерфейс. В составе "маленького окна" имеются кнопки вызова соответствующих методов - Show, Sound, Release и кнопка "Клонировать". Кнопка "Клонировать" "размножает диалог", т.е. она создаёт точно такое же окно - сёстринское по отношению к себе - и наделяет его копией существующего указателя на COM-интерфейс. Продвигая при этом счётчик ссылок.

Объекты CBanzai и CHello остались теми же - CBanzai остался статическим объектом сервера, а CHello - получается в динамической памяти. Поэтому "управлять временем жизни" имеет и смысл и видимый результат только для объекта CHello. Это не запрещено и для CBanzai, но вы увидите разницу сами.

Как следствие, вы можете получить объект и клонировать его, скажем, раза два... Три раза (при получении и дважды при клонировании) продвинется счётчик ссылок. А потом вы в произвольном порядке можете вызывать Release из всех этих "маленьких окон" - объект уничтожится только после третьего вызова Release. Операции new/delete в составе сервера переопределены на собственную реализацию. Она при вызове delete выдаёт на экран сообщение "освобождается блок памяти", т.е. вы воочию увидите когда именно объект уничтожается - когда срабатывает delete this. "Маленькое окно" закрывается кнопкой системного меню (крестик), а не кнопкой Release - это сделано для того, чтобы вы могли попробовать получить три копии объекта, а вызвать метод Release на один раз больше... У нас - небольшие модули, поэтому они и обрушиваются тоже быстро и без побочных последствий :)

Как обычно - пример хорошо откомментирован "по месту", мне здесь в этой статье больше добавить нечего. В нём всё должно быть понятно, а если что-то непонятно - напишите мне. Как работает пример и почему именно так - мы рассмотрим в cледующей статье, вместе с ответами на ваши возможные вопросы. А "что есть вообще COM-объект" уже должно быть понятно "практически".

Не стоит сейчас задавать вопросы "почему именно так подсчитываются ссылки" (не в смысле реализации AddRef/Release, а в смысле когда и откуда их вызывать) - это самостоятельная тема и на то будет специальная статья, а, может, и не одна.

предыдущий выпускархив и оглавлениеследующий выпуск
Авторские права © 2001 - 2004, Михаил Безверхов
Публикация требует разрешения автора

разделы сайта

форум

технология COM

оптимизация сайтов


© 2000-2004 Клуб программистов developing.ru