Добавлен: 28.03.2023
Просмотров: 48
Скачиваний: 2
Введение
Технология COM появилась в попытке Microsoft стандартизировать компонентную коммуникацию.
Глава 1. Краткий обзор технологии COM
COM, по сути, является формальным способом использования таблиц C ++ vtables [1] из C и других языков, поэтому вы можете создавать и использовать компоненты на любом языке, а также перезванивать между ними. Это способ выразить рациональное подмножество того, как классы C ++ работают и форматируют в памяти, способом, который может быть реализован на других языках.
Это было результатом языковых войн C / C ++ / Visual Basic в Microsoft.
Первоначальная 16-разрядная версия Visual Basic версии 1–3 имела механизм расширения подключаемого модуля под названием VBX - Расширения Visual Basic [2].
Они были чрезвычайно популярны и стали жертвой собственного успеха после того, как вокруг них выросла целая индустрия, и люди начали использовать их для всех видов вещей, для которых они не предназначены, и хотели использовать их из других языков и сред, таких как Борланд. Microsoft пришлось что-то предпринять, чтобы смягчить катастрофу успеха VBX, поэтому они изобрели COM.
В то время Microsoft переходила с Win16 на Win32, поэтому они разработали 32-битное определение COM, также известное как OCX или OLE Controls, которое они позже назвали ActiveX, потому что COM было очень трудно найти, и они хотели отвлечь внимание от Java новым модным словом.
Таким образом, они создали кучу уродливых макрологий на Си, которые позволили программистам на Си (или мастерам Visual Studio) определять COM-интерфейсы в заголовочных файлах и файлах реализации, которые просто распределяли память точно так же, как таблицы виртуальных классов С ++.
В то время как программы на C ++ будут использовать другие некрасивые макросы для объявления реальных честных классов C ++ для реализации интерфейсов COM.
И программисты Visual Basic ... делали бы то, что делали программисты Visual Basic.
Метод COM IUnknown :: QueryInterface [4] по сути похож на C ++ dynamic_cast [5]. Но он также добавляет некоторые функции агрегации объектов [6], которые позволяют объединять несколько подобъектов вместе путем агрегации вместо использования монолитного наследования. Вы можете реализовать «отрывные интерфейсы» [7], которые лениво создают агрегированные подобъекты по запросу, что полезно для реализации интерфейсов обратного вызова.
MFC (Microsoft Foundation Classes) - это набор оболочек C ++ для низкоуровневых интерфейсов Win32, а также огромный каркас для реализации графических элементов и диалоговых окон поверх Win32 и для обертывания интерфейсов OLE-автоматизации rube-goldbergesque вокруг классов C ++. Некоторое время MFC был основным способом реализации COM-интерфейсов в C ++, но он был печально знаменит тем, что был ужасно сложным, со всеми его уродливыми макросами, венгерской нотацией и странными соглашениями о программировании.
Позже Microsoft выпустила библиотеку ActiveX Template Library (ATL), предназначенную только для C ++ [8], которая, хотя и была достаточно уродливой, представляла собой более элегантный и мощный способ реализации COM-компонентов в C ++, но у нее не было багажа. поддержки C, и позволит вам реализовать компоненты COM / OLE / ActiveX без отвратительной инфраструктуры MFC. ATL был популярен для реализации всевозможных плагинов Internet Explorer.
На самом деле OLE был слоем интерфейсов COM и MIDL (Microsoft Interface Definition Language) поверх COM, который добавляет интерфейс IDispatch для динамического запроса и вызова методов и свойств во время выполнения, а также варианты типов [9]: теговые объединения для представления полиморфных данных. (т.е. типы данных VB) и передача параметров в функции OLE IDispatch.
OLE был связующим звеном, необходимым для интеграции компонентов COM в среду выполнения Visual Basic, поэтому он напрямую поддерживал типы данных Visual Basic, соглашения о вызовах и семантику, например индексированные свойства.
OLE также предоставил язык определения интерфейса (ILD), который вы могли бы скомпилировать в двоичные библиотеки типов, использовать для генерации шаблонных интерфейсов C и C ++, а OLE также имел COM-интерфейсы и структуры для предоставления этих библиотек типов во время выполнения. Он также имел много постоянства, отражения во время выполнения и пользовательского интерфейса для подключения компонентов и диалогов в окнах, предоставления таблиц свойств, редактирования и настройки элементов управления и т. Д.
MIDL поддерживал определение компонентов с помощью «двойных интерфейсов» [10]: как интерфейсов OLE IDispatch, принимающих параметры типа варианта, так и более эффективного низкоуровневого интерфейса COM, принимающего примитивные типы. Такие среды выполнения, как Visual Basic, знали, как интегрировать двойные интерфейсы и могли связываться с более эффективными базовыми интерфейсами COM, вместо того чтобы проходить через более медленные универсальные динамические интерфейсы IDispatch.
IDL также описал тонкости интерфейсов DCOM [11] (для внутрипроцессных и сетевых удаленных вызовов процедур), маршаллинга параметров [12] и всех других странных вещей. DCOM - это то, где COM ушёл в глубокий конец.
По сути, COM был по сути очень простой и оригинальной идеей, которая элегантно решала некоторые проблемы реального мира, но в конечном итоге превратилась в нечто чрезвычайно сложное, которое пыталось решить многие другие не связанные с этим проблемы, и которое требовало огромного количества инструментов, и это зависело от в среде Microsoft Visual Studio и Win32.
Microsoft фактически портировала ActiveX на Mac
Глава 2. Клиент - Серверная модель COM
В главе 1 упоминалось, как COM поддерживает модель взаимодействия клиент / сервер между пользователем сервисов объекта, клиентом и разработчиком этого объекта и его сервисами, сервером. Точнее говоря, клиент - это любой фрагмент кода (не обязательно приложение), который каким-то образом получает указатель, через который он может получить доступ к службам объекта, а затем при необходимости вызывает эти службы. Сервер представляет собой некоторый фрагмент кода, который реализует объект и структуры таким образом, что библиотека COM может сопоставить эту реализацию с идентификатором класса или CLSID. Участие идентификатора класса - это то, что отличает сервер от более общего разработчика объектов.
Библиотека COM использует CLSID для предоставления клиентам услуг «определения местоположения». Клиенту нужно только сообщить COM CLSID, который он хочет, и тип сервера - внутрипроцессного, локального или удаленного - что он позволяет COM загружать или запускать. COM, в свою очередь, находит реализацию этого класса и устанавливает связь между ним и клиентом. Эта связь между клиентом, COM и сервером показана на рисунке 2-2 на следующей странице.
В главе 1 также была представлена идея прозрачности расположения, когда клиентам и серверам никогда не нужно знать, насколько далеко они на самом деле находятся, то есть находятся ли они в одном процессе, в разных процессах или на разных машинах.
В этом разделе теперь подробнее рассматриваются механизмы COM, которые обеспечивают эту прозрачность, а также обязанности клиентских и серверных приложений.
Рисунок 2-2: Клиенты обнаруживают и получают доступ к объектам через сервисы определения местоположения в COM COM затем соединяет клиента с объектом на сервере. Сравните это с рисунком 1-2 в главе 1.
COM-объекты и идентификаторы классов
Класс COM - это конкретная реализация определенных интерфейсов; реализация состоит из машинного кода, который выполняется всякий раз, когда вы взаимодействуете с экземпляром класса COM. COM разработан, чтобы позволить классу использоваться различными приложениями, включая приложения, написанные без знания существования этого конкретного класса. Поэтому код класса существует либо в динамически связанной библиотеке (DLL), либо в другом приложении (EXE). COM определяет механизм, с помощью которого код класса может использоваться многими различными приложениями.
COM-объект - это объект, который идентифицируется уникальным 128-битным CLSID, который связывает класс объекта с определенной DLL или EXE в файловой системе. CLSID сам по себе является GUID (например, идентификатором интерфейса), поэтому никакой другой класс, независимо от того, какой поставщик его пишет, не имеет дублированного CLSID. Разработчики серверов обычно получают идентификаторы CLSID через функцию CoCreateGUID в COM или с помощью инструмента с поддержкой COM, который вызывает эту функцию изнутри.
Использование уникальных идентификаторов CLSID исключает возможность конфликтов имен между классами, поскольку идентификаторы CLSID никоим образом не связаны с именами, используемыми в базовой реализации. Так, например, два разных поставщика могут писать классы, которые они называют «StackClass», но каждый из них будет иметь уникальный CLSID и, следовательно, избегать любой возможности коллизии.
Кроме того, не требуется никакого центрального авторитетного и бюрократического органа для распределения или назначения идентификаторов CLSID. Таким образом, разработчики серверов по всему миру могут самостоятельно разрабатывать и развертывать свое программное обеспечение, не опасаясь случайного столкновения с программным обеспечением, написанным другими.
В своей хост-системе COM поддерживает базу данных регистрации (или «реестр») всех идентификаторов CLSID для серверов, установленных в системе, то есть сопоставление между каждым идентификатором CLSID и расположением библиотеки DLL или EXE, в которой находится сервер для этого. CLSID. COM обращается к этой базе данных всякий раз, когда клиент хочет создать экземпляр класса COM и использовать его сервисы. Этот клиент, однако, должен знать только CLSID, который не зависит от конкретного расположения DLL или EXE на конкретной машине.
Если запрошенный CLSID не найден в локальной базе данных регистрации, доступны различные другие административно-управляемые алгоритмы, с помощью которых можно попытаться найти реализацию в сети, к которой может быть подключен локальный компьютер; это объясняется более подробно ниже.
Учитывая CLSID, COM вызывает часть себя, называемую диспетчером управления службами (SCM [конечно, в разговорной речи произносится «scum»]), который является системным элементом, который находит код для этого CLSID. Код может существовать в виде DLL или EXE на том же компьютере или на другом компьютере: SCM изолирует большую часть COM, а также всех приложений от конкретных действий, необходимых для обнаружения кода. Мы вернемся к обсуждению SCM через минуту после изучения ролей клиентских и серверных приложений.
COM клиенты
Независимо от того, какое приложение передает CLSID в COM и запрашивает возвращенный экземпляр объекта, это COM-клиент. Конечно, так как этот клиент использует COM, это также приложение COM, которое должно выполнить необходимые шаги, описанные выше и в последующих главах.
Независимо от типа используемого сервера (внутрипроцессный, локальный или удаленный), COM-клиент всегда просит COM создавать экземпляры объектов одним и тем же способом. Простейший метод создания одного объекта - это вызов COM-функции CoCreateInstance. Это создает один объект с указанным CLSID и возвращает указатель интерфейса любого типа, который запрашивает клиент. Альтернативно, клиент может получить указатель интерфейса на то, что называется объектом «фабрики классов» для CLSID, вызвав CoGetClassObject. Эта фабрика классов поддерживает интерфейс под названием IClassFactory, через который клиент запрашивает у этой фабрики объект своего класса. На этом этапе у клиента есть указатели интерфейса для двух отдельных объектов, фабрики классов и объекта этого класса, каждый из которых имеет свой собственный счетчик ссылок. Это важное различие, которое проиллюстрировано на рисунке 2-3 и пояснено далее в главе 5.
Рисунок 2-3: COM-клиент создает объекты через фабрику классов.
Функция CoCreateInstance внутренне вызывает сам CoGetClassObject. Это просто более удобная функция для клиентов, которые хотят создать один объект.
Суть в том, что COM-клиент, в дополнение к своим обязанностям в качестве COM-приложения, отвечает за использование COM для получения фабрики классов, запроса этой фабрики для создания объекта, инициализации объекта и вызова этого объекта (и Фабрика классов) Функция выпуска, когда клиент закончил с этим. Эти шаги являются основной частью главы 5, которая также объясняет некоторые функции COM, которые позволяют клиентам управлять, когда серверы загружаются и выгружаются, для оптимизации производительности.
COM-серверы
Существует два основных типа объектных серверов:
На основе библиотеки динамических ссылок (DLL): сервер реализован в модуле, который можно загрузить в адресное пространство клиента и выполнять в нем. (Термин DLL используется в данной спецификации для описания любого механизма разделяемой библиотеки, который присутствует на данной платформе COM.)
На основе EXE: сервер реализован в виде отдельного исполняемого модуля.
Поскольку COM допускает распределенные объекты, он также позволяет реализовать два основных типа серверов на удаленной машине. Чтобы разрешить клиентским приложениям активировать удаленные объекты, COM определяет диспетчер управления службами (SCM), роль которого описана ниже в разделе «Библиотека COM».