Что такое «технология COM» и как с ней бороться?№5
С чего начинается COM?
С чего начинается
COM… Вопрос
достойный того, чтобы над ним хорошо
подумать. Наверное, COM все-таки начинается с
механизма взаимодействия объектов. Словом,
читателю придётся выдержать ещё немного
философии.
Объект - это абстракция прямо
отражающаяся в окружающей реальности. У
любой сущности видимого мира есть
состояние и поведение. В computer sciences
состояние описывается данными, а поведение
- процедурами. Объединив оба понятия в одну
сущность получим объект - классика, начиная
уже со времен Страуструпа! Является
теоремой, но сейчас доказывать уже не нужно - любая программа может быть
сконструирована как совокупность
взаимодействующих объектов. Вот и
посмотрим, как бы могли между собой
взаимодействовать части такой единой
программы. Соответствующая конфигурация
показана на рис. 1:
Рис.1 Конфигурация модуля, сконструированного в
ООП
Здесь имеется два
взаимодействующих объекта C и S которые
располагаются в одном исполняемом модуле, а
модуль, в свою очередь, располагается в
среде операционной системы. Расположение в
одном модуле позволяет «по рождению» знать
друг о друге все, что знал о них компилятор.
Также, здесь и ниже под термином «взаимодействие
С и S» мы имеем в виду, что C получил ссылку на
S и вызывает его метод.
Разделим модуль, изображённый на
рис.1 на два модуля, так чтобы в каждом
оказалось по одному объекту. Этим мы
разорвем их взаимодействие, но не уничтожим
способность объектов взаимодействовать
друг с другом - ведь сами-то объекты не
изменились. Сделать это можно, если один из
объектов поместить в DLL, а второй оставить в
EXE. Получим конфигурацию, изображённую на
рис. 2:
Рис. 2 Конфигурация разделенных
модулей
Рассмотрим возможный сценарий
такого взаимодействия. Сразу оговоримся -
сценарий «загрузки DLL по требованию» здесь
невозможен - модуль MC ничего не знает о
модуле MS. Это мы их наименовали так только
для нашего рассмотрения. Очевидно так же,
что модуль MC - загружен в память и
выполняется, а иначе как бы объект C мог
проявлять свои желания?
Итак, объект
C имеет твёрдое
намерение взаимодействовать с объектом S, а
объект S - такого желания совершенно не
испытывает и ведет себя пассивно: разыщут -
исполнит. Более того, вообще говоря, С и
вовсе неизвестно - есть ли «в живых» этот
самый объект S. Пока они оба «жили» в одном
модуле этой проблемы не было вовсе - и
адресное пространство было одно и ссылки на
объект из «своего» модуля создавались еще
компилятором. А сейчас… сейчас объект С
знает только, что где-то в природе должен
существовать объект S и хочет его достать.
Что должен делать объект
C? Что он
вообще может сделать? Разумно предположить,
что первое обращение последует от C к
операционной системе - «я знаю, что в твоих
недрах есть объект S, прошу выдать мне
ссылку на него». Система в таком случае
должна как-то вести учёт своего «объектного
поголовья» и иметь средства отличать одни
объекты от других. Без этой способности
запросы такого рода не выполнить. Адрес, как
характеристика объекта, здесь неприменим -
адрес памяти известен только для заведомо
существующих объектов, а C даже про
существование S ничего не знает. Кроме того,
система должна также знать, что объект S «живет»
именно в модуле MS, а этот модуль -
располагается во вполне определенном
каталоге файловой системы. О том, какие
модули составляют процесс, система знает и
так.
Система, получив такой запрос из
определенного процесса, должна просмотреть
свой список «имя объекта - имя модуля»,
отыскать по имени объекта модуль, в котором
тот обитает. После этого система, видимо,
должна проверить - а есть ли такой модуль в
числе составляющих процесс. Если такого
модуля нет, то система его должна в этот
процесс загрузить…
Как «сделать объект
S» система,
конечно, могла бы знать. Но - сколько модулей,
столько и мнений, и - все их помнить? Поэтому
система не будет пытаться что-то сделать
сама, а совершенно стандартным образом
запросит модуль MS - «выдать ссылку на объект
S». Тут появляется уже некоторая
возможность волюнтаризма со стороны модуля
MS - система-то просила у него только ссылку.
Как получается эта ссылка - создает ли
модуль новый объект S всякий раз, как его
запрашивают, имеет ли он объект S один на
всех и всем выдает одну и ту же ссылку - дело
модуля MS, а не системы.
Модуль
MS «проворачивается» - он «делает
объект S» в памяти, получает его адрес и
возвращает этот адрес системе - «получите,
что просили». Система же, зная, от кого
поступил запрос, возвращает адрес тому, кто
вызывал - объекту C. Поскольку объекты C и
S
раньше жили в одном модуле, то, как вызывать
методы объекта S объект C знает! А ссылку он
получил… Взаимодействие - состоялось.
Обратим внимание вот на что - в
этом, нестрого изложенном сценарии
взаимодействия, точно обозначены механизмы
и понятия, необходимые, чтобы объекты,
заведомо всё знающие о взаимодействии друг
с другом могли «друг друга повстречать».
Более того, эти механизмы и нужны только
лишь для того, чтобы можно было «обеспечить
встречу» - как взаимодействовать объекты и
сами знают. И вот эту инфраструктуру мы
изучим подробнее, ведь «вызов метода по
ссылке на объект» - совершенно стандартная
возможность, предоставляемая любым языком
программирования.