На этом шаге мы рассмотрим маршалинг и взаимодействие клиента с внутренними,
локальными и удаленными серверами.
Маршалинг был реализован в COM для решения проблемы экспорта объектов через адресное пространство процесса. Дальнейшее развитие COM-технологии, получившее название DCOM (Distributed COM), позволило осуществлять взаимодействие объектов, выполняющихся на различных компьютерах.
Единственным способом взаимодействия клиента с COM-объектом является использование интерфейсов. На этапе выполнения интерфейс характеризуется адресом, указывающим на другой указатель, который, в свою очередь, указывает на таблицу, содержащую адреса реализации каждой функции, экспортируемой интерфейсом (рисунок 1).
Рис.1. Структура интерфейса
Эта структура позволяет обеспечить маршалинг (marshalling) - пересылку указателя между процессами (и в общем случае между компьютерами, иногда называется "маршрутизация").
Реализация интерфейса COM-объекта представляет собой создание в памяти подобной структуры и предоставление указателя на нее. Весьма существенно, что адреса самих методов определяются на этапе выполнения помощью указателя на интерфейс в момент обращения к ним, а не хранятся в памяти статически. При наличии указателя на метод в таблице виртуальных методов всегда существует и его реализация, по этому клиент не должен ни обрабатывать сообщений об обращении к не существующим функциям, ни иметь собственной версии их реализации.
Когда клиенту требуется СОМ-объект, он пытается найти сервер, посылает серверу запрос на создание объекта, а затем получает от него указатель на исходный интерфейс, с помощью которого можно получить дополнительные указатели на другие интерфейсы этого объекта.
Местоположение сервера определяется на основании записи в реестре. Затем сервер загружается в оперативную память (если он еще не загружен или если требуется новый экземпляр сервера), создает нужный объект и возвращает клиенту указатель на интерфейс.
Если СОМ-сервер является внутренним, то есть выполненным в виде библиотеки DLL, она загружается в адресное пространство клиента с помощью функции Win32 API LoadLibrary. В этом случае значение указателя на интерфейс непосредственно доступно клиенту (рисунок 2).
Рис.2. Взаимодействие клиента с внутренним COM-сервером
Если сервер локальный, СОМ использует функцию CreateProcess, загружая исполняемый файл и инициализируя СОМ в адресном пространстве последнего. В этом случае обычно нет возможности передать клиенту значение указателя на интерфейс, так как это указатель на объект в другом адресном пространстве. В этом случае в адресных пространствах клиента и сервера создаются два объекта: stub (заглушка) - представитель клиента в адресном пространстве сервера, имеющий дело с реальным указателем на интерфейс, и proxy (заместитель) - представитель сервера в адресном пространстве клиента. Эти два объекта соединяются между собой с целью передачи клиентскому процессу указателя на интерфейс. В этом случае используется маршалинг, создающий так называемый marshalling packet - пакет данных, содержащий необходимую информацию для соединения с процессом, в котором создан объект. Этот пакет создается с помощью функции COM API CoMarshalInterface, затем он передается процессу клиента любым доступным способом, где другая функция CoUnMarshalInterface превращает этот пакет в указатель на интерфейс. Стандартный маршалинг осуществляется с помощью интерфейса IMarshall (рисунок 3). Методы CoMarshalInterface и CoUnMarshalInterface вызываются соответственно в реализациях методов интерфейса IMarshall MarshallInterface и UnMarshallInterface.
Рис.3. Взаимодействие клиента с локальным COM-сервером
Сходная технология используется при осуществлении вызовов удалённых процедур (RPC - Remote Procedure Calls), откуда она и была заимствована Microsoft.
Естественно, proxy-объект не содержит реализации методов интерфейса. Все аргументы вызываемых методов помещаются в пакет, передаваемый stub-объекту с использованием RPC. Stub-объект распаковывает переданные аргументы, помещает их в стек и обращается к реальному объекту, используя существующий указатель на интерфейс. Результат выполнения метода упаковывается в пакет и посылается proxy-объекту, который распаковывает его и передает клиенту.
В случае сервера, расположенного на удаленном компьютере, обращение к серверу СОМ соединяется со специальным резидентным процессом удаленного компьютера, контролирующим удаленный запуск сервисов на нем (наличие такого процесса диктуется обычными соображениями безопасности). Этот процесс, называемый иногда Service Control Manager (SCM), осуществляет запуск сервера на удаленном компьютере и возвращает указатель на интерфейс клиентскому компьютеру и клиентскому процессу. В остальном маршалинг осуществляется точно так же, как и в случае локального сервера, за исключением того, что proxy-объект и stub-oбъект, общаясь с помощью того же самого механизма RPC, физически находятся на разных компьютерах (рисунок 4).
Рис.4. Осуществление удалённого доступа к COM-серверу
Со следующего шага мы начнем рассматривать реализацию интерфейсов в Delphi.