Файл: Технология COM (Краткий обзор концепций программирования).pdf
Добавлен: 30.04.2023
Просмотров: 111
Скачиваний: 3
СОДЕРЖАНИЕ
Глава 1. История технологии СОМ
Краткий обзор концепций программирования
1.2 Предпосылки возникновения COM
1.4 Составляющие приложений COM
Глава 2. Реализация технологии СОМ
2.1 Способы реализации СОМ серверов
2.2 Пример реализации и использования COM класса в С++
Вызов этой функции целесообразно выполнить следующим образом:
if (m_pAccount)
{
m_pAccount->Release();
m_pAccount = NULL;
}
// создание экземпляра СОМ класса
if (!CreateAccount(&m_pAccount))
{
MessageBox("CreateAccount failed");
return;
}
После получения ссылки на интерфейс ею можно пользоваться для вызова методов класса, например, так:
int balance;
HRESULT hr = m_pAccount->GetBalance(&balance);
if (FAILED(hr))
{
MessageBox("GetBalance failed");
return;
}
Добавление других интерфейсов. Для реализации дополнительных интерфейсов необходимо проделать следующие шаги:
- объявить новый (абстрактный) класс как производный от IUnknown;
- сгенерировать для него идентификатор IID с помощью GuidGen.exe;
- объявить конкретный класс как производный от всех поддерживаемых объектом СОМ интерфейсов.
Например:
class IDisplay : public IUnknown
{
public:
// IDisplay methods
STDMETHOD(Show)() = 0;
};
Теперь используем множественное наследование и описываем класс конкретный:
class NewCAccount : public IAccount, IDisplay
{
…
}
Так как появился дополнительный интерфейс, необходимо изменить реализацию QueryInterface так, чтобы он позволял получать любой из интерфейсов IAccount и IDisplay. Пример реализации этого метода:
STDMETHODIMP
CAccount::QueryInterface(REFIID iid, void** ppv)
{
if (iid == IID_IUnknown)
*ppv = (IAccount*) this;
else if (iid == IID_IAccount)
*ppv = (IAccount*) this;
else if (iid == IID_IDisplay)
*ppv = (IDisplay*) this;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
Заключение
Термин "СОМ" представляет собой сокращение фразы Competent Object Model - компонентная объектная модель. Сутью данной технологии является то, что программы строятся из компонент, которые состоят из объектов. Само по себе это обстоятельство не является последней новостью в области программостроения - модульная архитектура и объектно-ориентированный подход к построению программ давно являются признанными стандартами de facto. Новостью является то, что является этими компонентами и объектами - ими является непосредственно исполняемый двоичный код. Не "включаемые исходные тексты" компилируемые совместно с проектом, не "библиотеки стандартных программ", присоединяемые линкером, а непосредственно исполняемые файлы, которые никак не надо "связывать" со своим проектом - их достаточно зарегистрировать в операционной системе и они будут доступны любой программе исполняющейся на данной машине. Т.е. их использование в своей программе производится "без использования операций сборки модуля".
Конечно, такая технология не является новой и называется "динамическая загрузка", она давно известна и её преимущества очевидны. А модули, которые позволяют загружать себя таким образом, называются DLL. И в системе, именуемой Microsoft Windows такая технология известна от самого её рождения... А DLL и есть тот самый "двоичный исполняемый модуль", который может быть присоединен к программе лишь на стадии её выполнения.
Однако, если просто весь проект распределить по нескольким динамическим библиотекам, то "двоичные компоненты" не получатся? Действительно, важнейший признак "компонентности" уже появится - исполняемую программу можно будет собирать из отдельных частей без операций сборки модуля. Но вот DLL - не компонент, DLL есть, если можно так выразиться, только "место обитания компонентов" используемых в программе. Ведь из программы-то вызываются вполне конкретные процедуры и функции, которые только расположены в DLL. Кроме того, вызовы процедур "из своего модуля" и "из DLL" - не одинаковые действия. Вызов процедуры, которая располагается внутри "своего" модуля требует знания только имени этой процедуры, а если процедура располагается в DLL, то нужно знать ещё и имя самой библиотеки. Модель же COM позволяет этого "не знать", т.е. вызов объектов COM из своей программы осуществляется без знания того, где они расположены. Достаточно знать имя объекта.
Другое отличие COM, уже от привычных объектов в стиле объектно-ориентированного программирования (ООП), состоит в том, что объекты ООП известны только компилятору. Это - абстракции, в которых мыслит программист и которые компилятор превращает в двоичные структуры "данные + код". Объекты ООП существующие в разных единицах компиляции и, тем более, помещенные в разные двоичные модули, ничего не могут друг о друге "знать" просто потому, что их там нет и никогда не было. Не случайно заголовочные файлы, содержащие описания всех объектов проекта, подаются на вход именно компилятора - потом они уже никому не нужны. Объекты же COM - действительно существуют в двоичном виде как объекты. И в таком качестве известны всем, кто испытывает в них нужду.
Технология COM есть технология, которая переносит все преимущества ООП, доступные программисту на уровне исходного текста, на двоичный уровень. Если в исходном тексте программист волен использовать "те" объекты и не использовать "эти", но теряет всяческий контроль над тем, что он делал, как только исходный текст был скомпилирован, то при использовании COM эти возможности сохраняются на протяжении всего жизненного цикла программы. Дополнительно к этому добавляются возможности разделения проекта на отдельные, повторноиспользуемые, и двоичные компоненты. Т.е., если в результате непосильного труда у программиста получается что-то хорошее и нужное, хотя бы частично, кому-то другому, то, оформив это в виде COM-сервера, он смело может это распространять, не рискуя что-то потерять - ведь контроль за исходным текстом остается у него. В то же время все пользователи этого объекта будут его использовать так же, как и свой, "родной", объект.
Идея экспорта объектов заключается в том, что один модуль создает объект, а другой его использует посредством обращения к методам (сервисам). Конечно, в экспорте простейших объектов обычно не возникает необходимости - любой программист может создать их в рамках одного приложения. Однако предположим, что где-то и кем-то был реализован достаточно сложный алгоритм распознавания текста в файле *.bmp, получаемом при сканировании документов. Конечно же, производители сканеров захотят предоставить дополнительные возможности покупателям и пожелают включить такое программное обеспечение и свой пакет. При этом любая фирма будет стараться свести к минимуму число приложений в своем пакете: по возможности все сервисы должны вызываться из одного приложения.
На первый взгляд эта проблема решается достаточно просто, по крайней мере когда в качестве другого модуля используется динамически загружаемая библиотека - DLL. В этом случае оба модуля содержатся в одном и том же адресном пространстве. Казалось бы, создадим в DLL объект, вызовем его методы из основного приложения - и данная задача решена. Однако это не так. Если использовать традиционное объектно-ориентированное программирование, то нельзя создать объект в одном модуле, а вызывать его методы в другом.
Вторая проблема возникает при обобщении первой проблемы. Соответственно программисту, использующему эту библиотеку, потребуется иметь под рукой документацию - список методов и список их формальных параметров. Их реализация "вручную" неизбежно приведет к ошибкам. Для исправления ошибок потребуется время, и при этом нет никакой гарантии, что все они будут обнаружены. Соответственно хотелось бы, чтобы сам объект мог информировать среду разработки о том, какие методы ему доступны и каковы списки их формальных параметров.
Этим не ограничиваются сложности работы с различными модулями. Например, если в одном из модулей была зарезервирована память для хранения данных, то в другом модуле нельзя ни освободить ее, ни изменить ее размер. Это связано с тем, что различные модули имеют разные менеджеры памяти. Если один модуль выделяет память, то в менеджере памяти другого модуля это никак не фиксируется. Для таких операций необходимо, чтобы был общий менеджер памяти.
Еще одна проблема возникает при обращении к объекту, созданному другим приложением. В этом случае указатель на объект в памяти, созданный в одном приложении, является недействительным для другого приложения. При передаче указателя из одного приложения в другое (это можно сделать, скопировав его в Clipboard или используя метод PostMessage), другое приложение будет обращаться совсем не к тем ячейкам оперативной памяти компьютера, где реально находятся данные. В лучшем случае сразу же произойдет исключение, в худшем - при попытке записи данных - будет разрушено ядро Windows. Эту проблему можно представить более глобально, если рассматривать возможность создания объекта на одном из компьютеров, а использовать его с помощью сети на другом.
Список использованной литературы
- Абросимова, М.А. Информационные технологии в государственном и муниципальном управлении: Учебное пособие / М.А. Абросимова. - М.: КноРус, 2018. - 248 c.
- Акперов, И.Г. Информационные технологии в менеджменте: Учебник / И.Г. Акперов, А.В. Сметанин, И.А. Коноплева. - М.: НИЦ ИНФРА-М, 2018. - 400 c.
- Атьков, О.Ю. Персональная телемедицина. Телемедицинские и информационные технологии реабилитации и управления здоровьем / О.Ю. Атьков, Ю.Ю. Кудряшов. - М.: Практика, 2015. - 248 c.
- Батоврина Е.В. Информационные технологии в управлении предприятием // Теория и практика управления: новые подходы. - М.: Университетский гуманитарный лицей, 2016.- 217 с.
- Берестнева О.Г. Информационные технологии в науке, управлении, социальной сфере и медицине: сборник научных трудов Международной научной конференции «Информационные технологии в науке, управлении, социальной сфере и медицине»/ Часть II / под ред. О.Г.Берестневой, О.М.Гергет; Национальный исследовательский Томский политехнический университет. − Томск: Изд-во Томского политехнического университета, 2017. − 397 с.
- Гасумова, С.Е. Информационные технологии в социальной сфере: Учебное пособие для бакалавров / С.Е. Гасумова. - М.: Дашков и К, 2015. - 312 c.
- Громов Ю.Ю. Информационные технологии : учебник / Ю. Ю. Громов, И. В. Дидрих, О. Г. Иванова, М. А. Ивановский, В. Г. Однолько. – Тамбов: Изд-во ФГБОУ ВПО «ТГТУ», 2015. – 260 с.
- Демьянова О.В. Информационные технологии // Проблемы современной экономики. – 2018. − №1 (33).
- Информационные системы и технологии: Научное издание. / Под ред. Ю.Ф. Тельнова. - М.: ЮНИТИ, 2016. - 303 c.
- Каткова Л.А. Информационно-технологическое перевооружение системы управления предприятием как фактор повышения конкурентоспособности предприятия. // Теория и практика общественного развития. – 2017.- №8.
- Корнеев, И.К. Информационные технологии в работе с документами: Учебник / И.К. Корнеев. - М.: Проспект, 2015. - 304 c.
- Котова В. А. Теоретические и методические основы реструктуризации бизнес модели промышленного предприятия: предпроектная стадия: Дисс. канд. экон. наук: 08.00.05/ Самарский. гос. эконом. ун-т. – С.: РГБ, 2016 — С. 171.
- Круглова О.В. Информационные технологии в управлении: учебное пособие. - Дзержинск: изд-во «Конкорд», 2016. – 134 с.
- Лбов Г.С., Полякова Г.Л. Информационные технологии в современном бизнесе // Вестник Сибирского государственного аэрокосмического университета имени академика М.Ф. Решетнева. – Красноярск, 2017. - Т.31- №5. - С. 42-45.
- Логинов, В.Н. Информационные технологии в государственном и муниципальном управлении: учебное пособие. -М: из-во КНОРУС, 2013. -240с.
- Максимов, Н.В. Современные информационные технологии: Учебное пособие / Н.В. Максимов, Т.Л. Партыка, И.И. Попов. - М.: Форум, 2018. - 512 c.
- Мамонова, Т.Е. Информационные технологии. лабораторный практикум: Учебное пособие для прикладного бакалавриата / Т.Е. Мамонова. - Люберцы: Юрайт, 2016. - 176 c.
- Маркова В.Д. Информационные технологии: сущность и инновационная составляющая // Проблемы современной экономики. – 2016. – № 21. – С. 38-42.
- Матушевская, Е.Г. Информационные технологии управления (для бакалавров) / Е.Г. Матушевская, А.Т. Рахманова. - М.: КноРус, 2017. - 240 c.
- Микрюков, В.Ю. Информационные технологии в государственном и муниципальном управлении / В.Ю. Микрюков. - М.: КноРус, 2017. - 248 c.
- Наумов А.А., Бах С.А. Информационная среда. Синтез, анализ, моделирование и оптимизация. - Новосибирск: «ОФСЕТ», 2017. – 307 с.
Репин В.В., Елиферов В.Г. Процессный подход к управлению. Моделирование бизнес-процессов. – М. РИА «Стандарты и качество», 2015. – 408 с. - Тельнов Ю. Ф. Интеллектуальные информационные системы. М.: МЭСИ, 2015.
- Титоренко Г.А. Информационные технологии в маркетинге : учебник / Под ред. Г. А. Титоренко. — М.: ЮНИТИ-ДАНА, 2016. — 335 с.
- Тихонов Э.Е. Информационные технологии в управлении: учебное пособие. — Ставрополь: Изд-во СКФУ, 2015. – 402 с.
- Федосеева Н.Н. Сущность и проблемы электронного документооборота в информационных технологиях // Юрист. – 2017. – №6. – С.61.
- Щипицина, Л.Ю. Информационные технологии в лингвистике: Учебное пособие / Л.Ю. Щипицина. - М.: Флинта, 2015. - 128 c.
Приложение 1
Последовательность событий при обращении клиента к серверу COM
Шаг 1. |
Клиентское приложение запрашивает интерфейс путем вызова конструктора сокласса. Сокласс является производным от класса TObject и содержит только два конструктора и больше никаких методов. Конструктор Create используется для внутрипроцессных или локальных серверов, а CreateRemote – для серверов, размещенных на удаленных компьютерах. Любой из этих конструкторов должен создать экземпляр объекта и возвратить указатель на первый интерфейс (интерфейс по умолчанию), предоставляемый COM объектом. В Delphi конструктор сокласса вызывает метод CreateComObject (для локального сервера) или CreateRemoteComObject (для удаленного сервера). В свою очередь метод CreateComObject вызывает функцию Win API CoCreateInstance (или CoCreateInstanceEx в случае удаленного сервера). Вот реализация метода CreateComObject в модуле ComObject: Function CreateComObject(const ClassID: TGUID): IUnknown; Begin OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result)); End; Функция-оболочка OleCheck предназначена для генерации исключительной ситуации в случае ошибки – и только. Главный параметр обсуждаемых функций – это идентификатор сокласса ClassID, который идентифицирует в реестре Windows библиотеку (или приложение), содержащую реализацию сервера. Вот содержимое ветви реестра HKEY_CLASSES_ROOTCLSID для зарегистрированного внутрипроцессного сервера: [{40BC0668-D946-11D5-BE01-ABCDCE4D71F9}] ="SmpCOM Object" InprocServer32="D:WORKDIRSIMPLECOMSIMPLECOM.DLL" InprocServer32"ThreadingModel"="Apartment" ProgID="SimpleCOM.SmpCOM" Version="1.0" TypeLib="{40BC0665-D946-11D5-BE01-ABCDCE4D71F9}" Первый GUID – это и есть идентификатор сокласса. Соответствующую константу (типа TGUID) Delphi по умолчанию именует с префиксом CLASS_, например, CLASS_SmpCOM. |
Шаг 2. |
Функция CoCreateInstance иницирует библиотеку COM, которая по идентификатору CLSID отыскивает в реестре библиотеку .dll (или приложение) и загружает ее в память |
Шаг 3. |
Создается экземпляр объекта фабрика класса. Для случая реализации сервера в виде библиотеки в ее секции инициализации содержится вызов конструктора класса TTypedComObjectFactory (для сервера с библиотекой типов) или TComObjectFactory (для сервера без библиотеки типов). Если сервер реализован в виде библиотеки, то вызов этого конструктора делается в секции инициализации библиотеки. Конструктор класса TTypedComObjectFactory в конечном итоге вызвает унаследованный конструктор класса TComObjectFactory. Параметры конструкторов определяют вид COM сервера и модель его функционирования |
Шаг 4. |
Конструктор сокласса создает COM объект и возвращает указатель на запрошенный интерфейс. Теперь клиентское приложение может вызывать методы интерфейса или, с помощью метода QueryInterface, может получить указатель на любой другой интерфейс, поддерживаемый объектом, по его идентификатору GUID |
Шаг 5. |
Объект COM самостоятельно ведет подсчет ссылок на его интерфейсы. Когда число этих ссылок равно нулю, COM объект уничтожается самостоятельно. Библиотека (или приложение) выгружается из памяти службами COM с помощью функции Win API CoFreeUnusedLibraries. Эта функция выгружает библиотеку с COM объектом в том случае, если функция DllCanUnloadNow возвращает значение S_OK. Реализация библиотеки сервера в соответствии со спецификацией COM должна экспортировать, в общем случае, всего 4 функции: DllGetClassObject, DllCanUnloadNow, DllRegisterServer и DllUnregisterServer |