Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Технология COM (Краткий обзор концепций программирования)

Содержание:

Введение

Представленная работа посвящена теме "Технология СОМ".

Актуальность настоящей работы обусловлена, с одной стороны, большим интересом к теме "Технология СОМ" в современной науке, с другой стороны, ее недостаточной разработанностью. Рассмотрение вопросов связанных с данной тематикой носит как теоретическую, так и практическую значимость.

Стандарт COM был разработан в 1993 году корпорацией Microsoft как основа для развития технологии OLE. Технология OLE 1.0 уже позволяла создавать т. н. «составные документы» (англ. compound documents): например, в пакете Microsoft Office эта технология позволяла включать диаграммы Microsoft Excel в документы Microsoft Word.

COM (англ. Component Object Model — модель компонентного объекта; произносится как [ком]) — это технологический стандарт от компании Microsoft, предназначенный для создания программного обеспечения на основе взаимодействующих компонентов объекта, каждый из которых может использоваться во многих программах одновременно. Стандарт воплощает в себе идеи полиморфизма и инкапсуляции объектно-ориентированного программирования. Стандарт COM мог бы быть универсальным и платформо-независимым, но закрепился в основном на операционных системах семейства Microsoft Windows. В современных версиях Windows COM используется очень широко. На основе COM были реализованы технологии: Microsoft OLE Automation, ActiveX, DCOM, COM+, DirectX, а также XPCOM.

Объектом данного исследования является технология СОМ.

При этом предметом исследования является реализация и использование COM технологии.

Целью исследования является изучение темы «Технология СОМ» с точки зрения новейших отечественных и зарубежных исследований по сходной проблематике.

В рамках достижения поставленной цели автором были поставлены и решения следующие задачи:

  1. Изучить краткий обзор концепций программирования.
  2. Сказать о предпосылках возникновения COM.
  3. Изложить введение в COM технологии.
  4. Обозначить составляющие приложений COM.
  5. Представить способы реализации СОМ серверов.
  6. Привести пример реализации и использования COM класса в С++.

Работа имеет традиционную структуру и включает в себя введение, основную часть, состоящую из 2 глав, заключение и список использованной литературы и 1 приложение.

Результаты могут быть использованы для разработки методики анализа "Технология СОМ".

Теоретическое значение изучения проблемы "Технология СОМ" заключается в том, что избранная для рассмотрения проблематика находится на стыке сразу нескольких научных дисциплин.

Глава 1. История технологии СОМ

Краткий обзор концепций программирования

История программирования насчитывает уже полвека, если начинать отсчет с середины 50-х годов, когда появился первый язык программирования высокого уровня Fortran. Этот язык получил широкое распространение и используется до сих пор. За эти полвека технология программирования обогатилась целым рядом не только практических методов, но и продуктивных концепций, которые и будут предметом краткого анализа в данном разделе. Хочется думать, что этот обзор поможет лучше понять главные тенденции развития программирования.

К настоящему времени я бы выделил такие основные концепции программирования:

- процедурное программирование;

- модульное программирование;

- объектно-ориентированное программирование;

- модель компонентных объектов COM.

Порядок перечисления этих концепций соответствует и хронологии их зарождения. Этапу процедурного программирования предшествовала та далекая пора, когда еще не было языков программирования, имеющих подпрограммы. Та технология, которая использовалась до появления подпрограмм, могла бы быть названа непроцедурным программированием. В настоящее время трудно даже представить себе программу, написанную без использования подпрограмм. В качестве эксперимента попробуйте написать на каком-нибудь языке программу, которая вводит два числа с клавиатуры и выводит на монитор их сумму. Скажете, это просто? Но ведь использовать какие-либо стандартные подпрограммы нельзя, если придерживаться технологии непроцедурного программирования [1].

Отметим, что методологии разработки программных продуктов ранее и, тем более, в настоящее время уделяется очень большое внимание, но даже краткое освещение ее основных результатов выходит за рамки не только этого раздела, но и данной работы в целом. По этой причине мы не будем здесь обсуждать, например, CASE-технологии, а рассмотрим только те парадигмы программирования, которые лежат в основе всех современных средств проектирования ПП и относятся преимущественно к языковым средствам. При этом рассматриваемые концепции программирования присущи и реализуемы в разных языковых средах, в том числе в С++ и Object Pascal. Надо отметить, что в языке С++ присутствует более широкий спектр средств, предназначенных, в первую очередь, для целей структурирования ПП.

При процедурном программировании мы размышляем в первую очередь о действиях, которые необходимо выполнить, а затем о данных. При этом подходе предметная область решаемой задачи отображается на множество операторов (процедур) и операндов (данных). Например, если нам надо использовать в программе (для MS DOS) окно, то мы будем проектировать процедуры прорисовки и прятанья окна, вывода информации в окно и др., а затем начнем думать о том, где и как хранить данные, относящиеся к окну. По всей видимости, мы достаточно быстро придем к мысли о том, что данные целесообразно объединить в записи. Вследствие такого подхода нам удастся избежать того хаоса, который был присущ программе, не имеющей процедур. Достаточно представить себе программу, содержащую хотя бы 1000 строк (а это совсем не большая программа), чтобы осознать тот факт, что даже если такую программу и удастся когда-нибудь отладить, то уж модифицировать ее и устранять неизбежные ошибки на этапе сопровождения простым смертным не под силу.

Кстати, чтобы по достоинству оценить роль и значение процедур, возьмите любую программу и посмотрите, сколько в ней используется процедур и функций: стандартных и собственных. Код хорошо написанной программы будет на 90% состоять из вызовов подпрограмм.

Таким образом, процедурное программирование, как и следует из его названия, позволяет хорошо реализовать алгоритмы обработки данных, расчленив их на отдельные подпрограммы, каждая из которых выполняет свою четко определенную функцию. С другой стороны, все обрабатываемые данные нам придется описать в глобальной области видимости и позаботиться о том, чтобы каждая подпрограмма получила именно те данные, которые ей необходимы. Проблема оптимальной организация и структурирования данных в большой программе является не менее актуальной, чем оптимальная декомпозиция программы на процедуры.

Наличие большого объема глобальных данных, характерное для процедурного подхода, устраняется в модульном программировании, концепция которого как раз и появилась как средство защиты от постоянно возрастающих размеров программ, и, соответственно, количества, объема и многообразия подпрограмм и обрабатываемых ими данных. Модуль является такой структурной единицей программы, которая объединяет (инкапсулирует) в единое целое данные и процедуры их обработки [4].

Такие языковые средства как модули (unit) в Object Pascal или пространства имен (namespaces) в С++ не только позволяют воплотить в реальных ПП концепцию модульного программирования, но и позволяют решить проблему конфликта имен, присущую большим программам.

В том же примере с таким важным элементом интерфейса программы, как окно, было бы целесообразно поместить в один модуль все процедуры работы с окном и данные, которые к нему относятся. Такой – модульный – подход позволяет добиться, по крайней мере, двух основных преимуществ:

- возможность простого использования модуля в других программах, причем пользователю модуля нет необходимости передавать исходный код модуля: ему достаточно откомпилированного кода;

- сокращение объема глобальных данных программы и сокрытие данных в модулях, что повышает надежность программы. В программе на Object Pascal важные данные можно легко скрыть от пользователя модуля, описав их в секции реализации.

Наглядным примером разумного использования модульного подхода являются целые библиотеки модулей, поставляемые вместе с Delphi. Как известно, эти модули содержат не только процедуры и функции, но и описания классов, констант, типов и, иногда, небольшого числа переменных.

Концепция объектно-ориентированного программирования (ООП) базируется на понятии объекта (класса) как типа данных языка программирования. В «Словаре по кибернетике» ООП называется «программированием, основанным на декомпозиции программируемой задачи на объекты. Система программ, осуществляющая решение задачи, рассматривается как совокупность активных объектов, взаимодействующих путем посылки сообщений».

Класс – определяемый программистом структурный тип, объединяющий данные и процедуры их обработки в единое целое. Упрощая понятие класса можно сказать, что он представляет собой такой структурный тип данных (тип record в Object Pascal и struct в С++), в который добавлены процедуры и функции. Данные класса часто называют его свойствами, а процедуры и функции – методами (обработки этих данных).

Следование концепции ООП предполагает выполнение такого анализа решаемой задачи, при котором, в первую очередь, идентифицируются объекты и их поведение. Для объектов необходимо выявить:

- данные, описывающие их свойства и состояние;

- функции, которые должны выполнять объекты;

- сообщения, которые могут получать объекты.

Таким образом, объект представляет собой структурный элемент программы, в котором локализована определенная часть знаний предметной области. Объект выполняет свои функции только в ответ на получение сообщений, благодаря чему ООП наиболее приспособлено для моделирования технических систем и систем с параллельными процессами.

В развитие предыдущих концепций ООП предлагает, в первую очередь, думать о классе как абстрактной модели реального или физического объекта. В отличие от концепции модуля как главного элемента модульного программирования, класс является, в первую очередь, типом, объединяющим данные и методы их обработки. Если вернуться к примеру с окном и сделать его классом, то данными класса будут размеры окна, его координаты, цветовые атрибуты, а методами – процедуры и функции, которые обеспечивают прорисовку окна, вывод в него данных.

Коль скоро класс является типом (данных), то для его использования в программе необходимо описать переменные этого типа, которые принято называть объектами или экземплярами класса. Отсюда следует, что разработка класса окно должна выполняться так, чтобы при необходимости использования в программе нескольких окон достаточно было просто объявить нужное число экземпляров класса, то есть переменных. Каждый объект имеет свой собственный набор данных, а функции объекта всегда присутствуют в программе в одном экземпляре.

Таким образом, если модуль инкапсулирует все данные, например, данные о всех окнах программы, то каждый объект содержит данные только об одном – «своем» – окне и не имеет доступа к данным других объектов. Это обстоятельство является одним из важных преимуществ ООП по сравнению с модульным программированием [7].

Если инкапсуляция является первым принципом ООП, то его вторым важнейшим принципом является наследование. Наследование есть возможность порождать новые классы на основе уже существующих, причем порожденный класс (наследник) наследует все данные и методы родительского класса и может иметь (и обычно имеет) свои собственные.

Принцип наследования позволяет достичь двух важнейших целей.

Во-первых, это простой и удобный способ повторного использования кода. Достаточно часто разработка нового класса начинается не «с нуля», а базируется на расширении возможностей уже существующего класса. В этом случае разработчику нового класса нет необходимости разбирать «чужой» программный код – обычно он даже не имеет исходного кода, а располагает только спецификацией класса – ему необходимо реализовать в своем классе только недостающие методы или перекрыть те методы, функциональная возможность которых не отвечает поставленным требованиям.

Во-вторых, следование принципу наследования позволяет построить иерархию классов, которая отражает классификацию реальных или виртуальных объектов реального мира. Иерархия классов позволяет иметь методы и данные, совместно и единообразно используемые объектами всей иерархии. Использование третьего принципа ООП – полиморфизма – позволяет создавать, в пределах одной иерархии классов, полиморфные объекты.

Концепция, лежащая в основе модели компонентных объектов (COM – Component Object Model), будет рассмотрена в следующем разделе.

1.2 Предпосылки возникновения COM

Технология СОМ является одной из базовых технологий Windows и для того, чтобы понять ее назначение, необходимо рассмотреть основные предпосылки ее возникновения. Если попытаться кратко сформулировать ее цель – то это способ взаимодействия клиентских приложений и серверов или предоставление сервисов одним приложением другому. Таким образом, главной предпосылкой возникновения СОМ является именно взаимодействие приложений.

Проблема взаимодействия приложений Windows имеет две стороны: взаимодействие на одном компьютере и в сети Intranet или Internet. Взаимодействие приложений, размещенных на удаленных компьютерах, обеспечивается технологией DCOM (Distributed COM – распределенная модель компонентных объектов), а также и технологией COM+. COM+ является следующим эволюционным шагом в развитии технологии СОМ. Технология COM+ не только включает в себя технологии COM и DCOM, но и имеет свои специфические особенности, облегчающие программирование взаимодействующих приложений Windows в рамках одного компьютера или в сети.

Чтобы яснее представить себе проблему взаимодействия приложений Windows, надо вспомнить следующее. Каждый процесс в 32-разрядной Windows имеет свое адресное пространство размером в 4Гб и, по этой причине, один процесс не имеет никакой возможности (и хорошо!) получить доступ к данным или функциям другого процесса, так как любой адрес в процессе ссылается на свое адресное пространство.

В логической и хронологической последовательности взаимодействие приложений Windows реализовалось с использованием следующих технологий:

1 Dynamic Link Libraries (DLL) – динамически подключаемые библиотеки.

2 Open DataBase Connectivity (ODBC) – открытый интерфейс доступа к базам данных, встроенный в Windows и Windows NT.

3 Dynamic Data Exchange (DDE) – динамический обмен данными.

4 Object Linking and Embedding (OLE1.0) – внедрение и связывание объектов.

5 OLE2.0 – OLE на базе COM.

6 Distributed COM (DCOM) – распределенная модель компонентных объектов.

7 COM+ – новейшая технология COM.

Ну хорошо, скажете Вы, а зачем вообще приложениям необходимо взаимодействовать друг с другом? Если некоторому приложению необходимо, допустим, использовать электронные таблицы Excel, то почему бы ему не подключить соответствующую библиотеку DLL? Естественно, можно, и это уже было первым подходом к решению обсуждаемой проблемы. Однако, такой подход имеет свои недостатки, главным из которых является проблема сопровождения и модификации ПП. Если разрабатывалась новая версия какой-либо функции DLL, то перестают работать приложения, которые используют старую версию библиотеки. Если новую версию функции снабдить новым именем, то необходимо разрабатывать новую документацию и включать в библиотеку обе версии функции. Несложно себе представить, в какой конгломерат превратится библиотека в течение весьма небольшого промежутка времени и насколько сложно будет ориентироваться в многочисленных версиях функций!

Главную идею технологии ODBC можно проиллюстрировать все на той же Excel. Так как это приложение должно быть способно считывать данные из БД различных форматов, необходимо или разрабатывать различные версии Excel для каждой из БД (Excel для Access, Excel для Oracle и т.д.) или заблаговременно подключать все необходимые библиотеки к Excel. Microsoft выбрала другой путь, создав промежуточный программный слой, который определяет стандартный интерфейс для приложений. На уровне вызовов этот интерфейс использует язык SQL, а реализация взаимодействия с БД обеспечивается драйверами, поставляемые в форме DLL. Таким образом, ODBC располагается между приложением и источниками данных различных форматов [8].

Технологию динамического обмена данными DDE можно рассматривать как попытку стандартизации обмена данными между приложениями. Вся идеология Windows основана на обработке сообщений (messages) и любые приложения могут обмениваться друг с другом сообщениями, используя общую очередь сообщений. Проблема, однако, состоит в том, что каждое из приложений должно знать протокол обмена данными, т.е. формат сообщений, и собственно сообщения Windows не позволяют передавать сравнительно большие объемы данных. Технология DDE как раз и предложила такой стандартный протокол, реализованный во многих приложениях. Главными недостатками DDE является сложность программирования, ненадежность и то обстоятельство, что приложения должны знать формат передаваемых данных.

Технологию внедрения и связывания объектов[1] OLE1.0 фирма Microsoft представила в 1991г. как попытку реализации объектно-ориентированного механизма взаимодействия приложений. Главной идеей OLE является концепция составного документа, который может содержать объекты других приложений.

До OLE приложения могли обмениваться статическими снимками данных через буфер обмена Windows. Однако редактирование таких данных должно выполняться тем приложением, которое их породило, а после редактирования они вновь должны быть вставлены в другой документ. Если изменяются исходные данные, то, очевидно, должны изменяться данные и в составном документе. Однако, системный буфер обмена не имеет никаких средств поддержания таких связей. Более того, проблемы возникают и при перемещении исходных данных в новое место.

Внедренный с помощью OLE1.0 объект содержит статические данные (рисунок) и данные, необходимые для его редактирования. Для редактирования объекта пользователю приложения-контейнера необходимо щелкнуть по объекту, вследствие чего в отдельном окне запускается исходное приложение, породившее эти данные. По окончании редактирования пользователь может сохранить данные и эти данные будут обновлены и в приложении-контейнере.

Недостатками технологии OLE1.0 являются:

1 Так как базовым механизмом OLE1.0 является DDE, который по своей природе асинхронен, то после вызова любой функции возврат управления происходит немедленно и требуется ожидать, в цикле, завершения требуемой операции.

2 Так как для передачи данных между приложениями используется разделяемая глобальная память, то данные сначала копируются в нее, откуда они тут же могут быть вытолкнуты Windows в файл подкачки, вследствие чего замедляется работа приложения.

3 Связи OLE1.0 легко разрываются при перемещении файлов.

4 Пользователю неудобно редактировать данные в отдельном окне.

1.3 Введение в COM технологии

Далее рассмотрим основные понятия и определения.

COM (Component Object Model) – модель компонентных объектов Microsoft. Стандартный механизм, включающий интерфейсы, с помощью которых одни объекты предоставляют свои сервисы другим. Является основой многих объектных технологий, в том числе OLE и ActiveX. Другой перевод: многокомпонентная модель объектов.

DCOM (Distributed Component Object Model) – распределенная модель компонентных объектов. Расширение модели COM фирмы Microsoft, ориентированное на поддержку и интеграцию распределенных объектных приложений, функционирующих в сети.

COM представляет собой основанную на объектах клиент-серверную модель, разработанную Microsoft для обеспечения взаимодействия между компонентами программного обеспечения и приложениями. Microsoft расширила эту технологию добавлением элементов ActiveX, которые представляют результат развития технологий OLE и OCX. OCX (OLE Custom eXtension) – это программируемые компоненты-приложения с интерфейсом на базе OLE, позволяющим легко включать их в другие приложения. С 1996 года они стали называться ActiveX.

Сейчас Microsoft предлагает использовать термин Active technologies вместо ActiveX, включая в новые технологии такие составляющие:

1. Active Documents (активные документы).

2. ActiveX (управляющие элементы).

3. Active Scripting controls.

4. Automation (автоматизация, прежде известная как OLE Automation).

Ключевым аспектом COM является то, что эта технология обеспечивает связь между клиентами и серверами посредством интерфейсов. Именно интерфейс предоставляет клиенту способ "узнать" у сервера, какие именно возможности он поддерживает на этапе выполнения. Для расширения возможностей сервера необходимо просто добавить новый интерфейс к существующим.

Delphi предоставляет программисту мастеров (wizards) и классы, которые облегчают разработку приложений, основанных на технологиях COM. Мастера позволяют создавать:

1) простые COM–совместимые классы для использования в одном приложении;

2) полновесные серверы COM;

3) серверы автоматизации (Automation servers) и контроллеры автоматизации (Automation controller);

4) управляющие элементы ActiveX;

5) активные формы ActiveForms.

Технология COM как спецификация и реализация. COM является одновременно и спецификацией и реализацией. Спецификация COM определяет правила создания объектов и их взаимодействия, способ связи между объектами. В соответствии со спецификацией объекты COM могут быть написаны на различных языках, выполняться в адресном пространстве различных процессов и на разнообразных платформах. До тех пор, пока объекты полностью соответствуют спецификации, они могут взаимодействовать. Это позволяет объединять унаследованный код как компонент с новыми компонентами, разработанными в любом из объектно-ориентированных языков.

COM как реализация представляет собой библиотеку (файлы OLE32.dll OLEAut32.dll), которая предоставляет ряд основных служб, поддерживающих описанные спецификации. Библиотека COM содержит набор стандартных интерфейсов, определяющих основную функциональность объектов COM, и небольшой набор функций API, разработанных для целей создания и управления объектами COM.

Интерфейсы объектов Delphi, как и язык Object Pascal, соответствуют COM спецификации. Реализация COM в Delphi называется DAX (Delphi ActiveX framework – базовая структура (каркас) элементов ActiveX Delphi). Основная часть реализации этой структуры находится в модуле AxCtrls.

Когда программист использует мастеров Delphi или объекты библиотеки VCL в своем приложении, он использует реализацию COM спецификаций. Кроме того, Delphi предоставляет ряд упаковщиков (wrapper) для таких служб COM, которые не реализуются непосредственно, например, активные документы (Active Documents). Эти упаковщики включены в модуль ComObj

Так как COM является развивающейся технологией, она может быть расширена за рамки базисных служб. COM является основой для других технологий, таких как автоматизация (Automation – вместо прежнего термина OLE Automation), элементы ActiveX и активные документы (Active Documents).

Кроме того, в настоящее время возможно создание таких объектов COM, которые могут взаимодействовать с Microsoft Transaction Server (MTS). MTS – это система обработки транзакций, предназначенная для построения, развертывания и управления большими Intranet и Internet приложениями-серверами. Хотя MTS архитектурно и не является частью COM, она разработана для расширения возможностей COM в большой, распределенной среде.

Delphi снабжает программиста мастерами, облегчающими разработку приложений, которые объединяют упомянутые выше технологии – Automation, ActiveX, Active Documents и MTS [9].

1.4 Составляющие приложений COM

При разработке приложений, использующих технологию COM, используются структурные элементы, приведенные в таблице 1.

Таблица 1- Структурные элементы технологии COM

Элемент

Назначение

COM Interface

Средство, с помощью которого объект COM предоставляет свои функциональные возможности (службы) для внешних клиентов. Объект COM снабжает интерфейсом каждый набор методов и свойств. Любой объект COM имеет один или более интерфейсов

COM server

Некоторый модуль (EXE, DLL или OCX), который содержит код для объекта COM

COM client

Программный код, который получает требуемые услуги от сервера через интерфейс(ы) объекта COM. Клиент знает, что он хочет получить от сервера, но не знает как его запрос выполняется внутри сервера. В большинстве случаев клиент реализуется как Automation controller (то же, что и ActiveX-клиент)

Type Library

Библиотека типов, которая содержит описание COM объекта, его интерфейсов и методов, а также их GUID идентификаторы. Информация из библиотеки записывается в системный реестр и используется клиентским приложением. Delphi предоставляет специальный редактор библиотеки типов, а содержимое библиотеки типов представляет в виде обычного модуля на языке Object Pascal

Class Factory

Фабрика классов, экземпляр объекта которой создает COM объект. Сам объект фабрики классов создается COM сервером при запросе клиентским приложением первого интерфейса

Клиент взаимодействует с объектом COM посредством интерфейса, который представляет собой набор функционально или семантически связанных подпрограмм, с помощью которых обеспечивается связь клиента с провайдером сервисов (сервером). Стандартный способ изображения интерфейса приведен на рис.1.

Рис. 1. Интерфейс COM [10]

Например, каждый COM объект имеет базовый интерфейс IUnknown, который сообщает, какие интерфейсы объекта доступны клиенту. Любой интерфейс сообщает клиенту, какие возможности он предоставляет.

Ключевыми аспектами интерфейсов объектов COM являются следующие:

- будучи однажды опубликованным, интерфейс не должен изменяться ни при каких обстоятельствах. При необходимости расширение функциональности должно быть выполнено за счет добавления других интерфейсов;

- по соглашению, имя интерфейса должен начинаться с заглавной буквы I, например, IMalloc или IPersist;

- интерфейс имеет гарантированный уникальный идентификатор GUID (Globally Unique Identifier), который представляет собой 128-битное случайное число. Эти идентификаторы называют Interface Identifiers (IIDs). Использование таких идентификаторов ограничивает возможность конфликтов между разными версиями или продуктами;

- интерфейсы обладают языковой независимостью. Для реализации интерфейса может быть использован любой язык программирования, который поддерживает указатели и структуры и позволяет вызвать функцию по указателю на нее;

- сами по себе интерфейсы не являются объектами, а предоставляют способ получения доступ к объекту, а клиент получает доступ к данным объекта посредством вызова функций;

- любой интерфейс является наследником базового интерфейса IUnknown;

- обращения к интерфейсам могут перенаправляться между потоками, процессами и сетевыми компьютерами невидимо для клиента.

Базовый интерфейс IUnknown –‘тот интерфейс, который должны поддерживать все COM объекты, включает следующие подпрограммы:

1) QueryInterface;

2)AddRef;

3) Release.

Метод QueryInterface, объявленный как

Function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;

возвращает клиенту указатель на запрошенный интерфейс IID. С помощью полученного указателя клиент может вызвать любой из реализованных методов интерфейса. В качестве IID клиент может указать тип класса интерфейс – в этом случае компилятор самостоятельно извлекает соответствующий GUID.

Методы AddRef и Release используются для того, чтобы объект COM мог самостоятельно отслеживать продолжительность своего существования. Эти методы просто изменяют число ссылок на объект. Когда число ссылок на объект становится равным нулю, объект удаляется из памяти COM сервером.

Сервер COM является приложением или библиотекой, которая предоставляет сервис клиентскому приложению (или библиотеке). Сервер включает по крайней мере один объект COM, который в свою очередь представляет собой совокупность методов и свойств. Клиент не обязан знать, где в памяти располагаются объекты COM.

Когда клиент запрашивает сервис у объекта COM, он (клиент) должен передать идентификатор класса CLSID (class identifier). Идентификатор класса CLSID создается на основе GUID интерфейса объекта COM.

По идентификатору класса CLSID COM определяет соответствующий сервер, загружает его в память и сервер создает экземпляр объекта COM. Экземпляры объектов COM создает фабрика классов (class factory), к которой обращается сервер. Фабрика классов имеет свой интерфейс IClassFactory.

COM объект является экземпляром класса CoClass, в котором реализованы один или более интерфейсов COM. Объект COM обеспечивает те сервисы, которые определены в интерфейсах класса CoClass.

Экземпляры класса CoClass создаются специальным типом объекта, который называется фабрикой класса. Когда клиент обращается к COM объекту, фабрика класса создает экземпляр объекта и регистрирует экземпляр объекта для этого конкретного клиента. Если в это время другой клиент обращается к объекту, фабрика классов для него также создает (другой) экземпляр объекта.

Любой класс CoClass должен иметь фабрику классов и идентификатор класса CLSID, так что экземпляр COM объекта этого класса может быть создан извне, т.е. из другого модуля. Благодаря наличию у классов CoClass уникального идентификатора CLSID, они могут быть обновлены в любое время, как только для класса разработан новый интерфейс. Новый интерфейс может использовать модифицированные или новые методы и это не оказывает никакого влияния на прежние версии. В случае использования обычных библиотек DLL подобная ситуация прежде была типичной проблемой.

Мастера Delphi избавляют программиста от необходимости заниматься созданием объектов, которые обеспечивают функционирование фабрики классов.

Таким образом, COM - многообещающая и перспективная технология, находящаяся в русле общего направления развития программных технологий. С помощью COM можно разрабатывать программы и программные комплексы разного масштаба, функциональности и назначения. COM - социально-ориентированная технология.

Технология COM - сложная технология. Сложная как в концепции, так и в реализации. Она - намного сложнее, чем технология С++, реализуемая компилятором. Эта сложность не должна пугать - к настоящему времени разработано достаточное количество инструментов и средств разработки, которые позволяют "легко писать" и "легко использовать" COM-компоненты. Но эта сложность есть. На её преодоление тратятся ресурсы компьютера во время выполнения, а слабо понимающий концепции COM программист, несмотря на все эти редакторы, не сможет создать что-то приемлемо работающее, большее, чем примитивный пример. К счастью, это стандартная проблема - умение программировать есть не умение писать код, а только умение мыслить соответствующими категориями и конструкциями. И на VB можно написать плохо работающую программу, хотя на C++ сделать это значительно легче. Никакая технология не в состоянии предложить приемлемого решения этой проблемы - технические средства могут только избавить от рутины, но не от необходимости думать и понимать.

Глава 2. Реализация технологии СОМ

2.1 Способы реализации СОМ серверов

При работе с объектами COM клиент не знает, где находится объект. Он просто обращается к объекту посредством его интерфейса. Далее библиотека COM выполняет все необходимые шаги для удовлетворения вызова клиента.

Эти шаги зависят от конкретного местонахождения объекта COM: в том же процессе, что и клиент, в другом процессе на машине клиента или на другой машине в сети. В зависимости от этого различают три вида серверов COM.

Сервер в клиентском процессе (In-process server). Это библиотека DLL, которая выполняется в адресном пространстве процесса клиента. Например, элемент ActiveX, внедренный в Web страницу, выполняется в Internet Explorer или другом браузере. Это значит, что объект ActiveX загружается на машину клиента и выполняется в том же процессе, что и Web браузер. Клиент обращается к объекту COM путем прямого вызова интерфейса COM.

Рис. 2. Сервер в клиентском процессе [10]

Локальный сервер (local server). Он представляет собой другое приложение (файл *.exe), которое выполняется в другом адресном пространстве, но на том же компьютере, что и клиентское приложение. Например, обработка таблицы Excell, внедренной в документ Word, выполняется приложением Excell. Локальный сервер связывается с клиентом посредством COM библиотек.

Рис.3. Локальный сервер [10]

Когда объект COM принадлежит другому процессу на том же компьютере, что и клиентское приложение, или вовсе на другом компьютере (в сети), COM использует так называемого "заместителя" (proxy) для того, чтобы инициировать удаленный вызов процедуры (remote procedure call – RPC). Так как заместитель находится в клиентском процессе, то с точки зрения клиента обращения к интерфейсам выглядят так же, как и для случая размещения сервера в клиентском процессе. Заместитель перехватывает вызовы клиента и отправляет их туда, где находится сервер. Механизм, который позволяет клиенту получить доступ к объекту, находящемуся в другом процессе или на другом компьютере (невидимо для клиента), называется маршалингом или маршализацией.

Рис. 4. Маршализация [10]

Удаленный сервер (remote server). Он представляет собой библиотеку (DLL или OCX) или другое приложение, которые выполняются на другом компьютере, а не на машине клиента. Например, клиентское приложение, использующее базу данных, связывается с приложением, выполняемым на другом компьютере в сети. В этом случае удаленный сервер использует интерфейсы DCOM.

Рис. Удаленный сервер

Различие между локальным и удаленным сервером состоит в применяемом способе (и инструментальных средствах) взаимодействия клиента и сервера: в первом случае используется COM, а во втором – DCOM.

Если сервер реализован как библиотека (а библиотека не может выполняться как самостоятельное приложение), то COM создает специальное приложение-суррогат (surrogate), в рамках которого и выполняется библиотека.

Маршалинг. Механизм маршалинга позволяет клиентскому приложению делать вызовы методов интерфейса для объекта COM, который находится в другом процессе или на другом компьютере.

При любом вызове функций посредством интерфейса клиентское приложение помещает фактические параметры функции в стек и выполняет ее вызов. Если функция не находится в клиентском процессе, то вызов передается заместителю. Заместитель упаковывает параметры в пакет и передает их удаленному объекту. Заглушка COM объекта распаковывает пакет, помещает аргументы в стек и вызывает объект COM. Таким образом объект COM обрабатывает запрос клиента в своем собственном адресном пространстве.

Какой именно маршалинг будет реализован, зависит от реализации COM объекта. Стандартный механизм реализован интерфейсом IDispatch. Кроме того, объекты могут самостоятельно выполнять маршалинг, однако это довольно сложно.

Отметим, что технология Microsoft Transaction Server (MTS) обеспечивает дополнительную поддержку для удаленных объектов.

2.2 Пример реализации и использования COM класса в С++

В этом подразделе рассматривается весь процесс создания локального СОМ объекта, реализованного непосредственно в приложении.

Описание класса IUnknown в файле ..\Vc98\Include\Unknwn.h:

struct IUnknown

{

virtual HRESULT STDMETHODCALLTYPE QueryInterface(

/* [in] */ REFIID riid,

/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)=0 ;

virtual ULONG STDMETHODCALLTYPE AddRef( void) =0;

virtual ULONG STDMETHODCALLTYPE Release( void) =0;

};

Смысл использованных макросов:

HRESULT – long;

STDMETHODCALLTYPE – _stdcall

REFIID – const GUID &

В файле Unknwn.h можно найти также много других описаний, определяющих структуру таблицы vtable, заголовки функций для вызова proxy и stub и т.д. [12]

Описание (базового) класса IAccount – наследника IUnknown – как абстрактного класса:

class IAccount : public IUnknown

{

public:

// IAccount methods

STDMETHOD(GetBalance)(int* pBalance) = 0;

STDMETHOD(Deposit)(int amount) = 0;

};

8. Здесь STDMETHOD – virtual HRESULT _stdcall.

Описание (конкретного) класса СAccount:

class CAccount : public IAccount

{

public:

CAccount() // конструктор

{

m_nRef = 0;

m_nBalance = 100;

}

// методы IUnknown

STDMETHOD(QueryInterface)(REFIID, void**);

STDMETHOD_(ULONG, AddRef)();

STDMETHOD_(ULONG, Release)();

// IAccount methods

STDMETHOD(GetBalance)(int* pBalance);

STDMETHOD(Deposit)(int amount);

protected:

ULONG m_nRef; // число ссылок

int m_nBalance; // счет в банке

};

Использованные макросы:

9. REFIID – GUID (структура из 16 байт);

10. STDMETHODIMP – HRESULT _stdcall.

11.

Реализация методов класса CAccount:

STDMETHODIMP

CAccount::QueryInterface(REFIID iid, void** ppv)

{

if (iid == IID_IUnknown)

*ppv = (IAccount*) this;

else if (iid == IID_IAccount)

*ppv = (IAccount*) this;

else

{

*ppv = NULL;

return E_NOINTERFACE;

}

AddRef();

return NOERROR;

}

Метод QueryInterface в конечном итоге возвращает ссылку на таблицу vtable, которая создается компилятором С++ автоматически, если в классе определены виртуальные функции.

STDMETHODIMP_(ULONG) CAccount :: AddRef()

{

return ++m_nRef;

}

STDMETHODIMP_(ULONG) CAccount :: Release()

{

if(--m_nRef == 0)

{

delete this; // уничтожение экземпляра класса

// Trace("Object destroyed", "CAccount");

return 0;

}

return m_nRef;

}

STDMETHODIMP CAccount :: Deposit(int amount)

{

m_nBalance += amount;

return S_OK;

}

STDMETHODIMP CAccount::GetBalance(int* pBalance)

{

*pBalance = m_nBalance;

return S_OK;

}

Для практического использования класса CAccount требуется описать экземпляр класса IAccount:

IAccount * m_pAccount=NULL;

и получить ссылку на интерфейс. Эту задачу решает (обычная) функция CreateAccount.

BOOL CreateAccount(IAccount ** ppAccount)

{

HRESULT hr;

if (ppAccount == NULL)

return FALSE;

// Create object

CAccount* pAccount = new CAccount;

if (pAccount == NULL)

return FALSE;

// получить интерфейс. При этом в QueryInterface вызывается метод AddRef

hr = pAccount->QueryInterface(IID_IAccount, (void**) ppAccount);

if (SUCCEEDED(hr))

{

Trace("Object created", "CAccount");

return TRUE;

}

else

{

delete pAccount;

return FALSE;

}

}

Идентификатор интерфейса можно получить с помощью GuidGen и описать его как константу, например:

static const IID IID_IDisplay =

{ 0x5723b700, 0x2878, 0x11d1, { 0xa0, 0x1b, 0x0, 0xa0, 0x24, 0xd0, 0x66, 0x32 } };

Идентификатор для интерфейса IUnknown предопределен.

Невзирая на то, что в функции CreateAccount указатель pAccount на экземпляр класса создается локально, объект может быть разрушен, так как ссылка на него сохраняется в параметре ppAccount. Экземпляр СОМ класса уничтожается в методе Release.

Вызов этой функции целесообразно выполнить следующим образом:

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. Эту проблему можно представить более глобально, если рассматривать возможность создания объекта на одном из компьютеров, а использовать его с помощью сети на другом.

Список использованной литературы

  1. Абросимова, М.А. Информационные технологии в государственном и муниципальном управлении: Учебное пособие / М.А. Абросимова. - М.: КноРус, 2018. - 248 c.
  2. Акперов, И.Г. Информационные технологии в менеджменте: Учебник / И.Г. Акперов, А.В. Сметанин, И.А. Коноплева. - М.: НИЦ ИНФРА-М, 2018. - 400 c.
  3. Атьков, О.Ю. Персональная телемедицина. Телемедицинские и информационные технологии реабилитации и управления здоровьем / О.Ю. Атьков, Ю.Ю. Кудряшов. - М.: Практика, 2015. - 248 c.
  4. Батоврина Е.В. Информационные технологии в управлении предприятием // Теория и практика управления: новые подходы. - М.: Университетский гуманитарный лицей, 2016.- 217 с.
  5. Берестнева О.Г. Информационные технологии в науке, управлении, социальной сфере и медицине: сборник научных трудов Международной научной конференции «Информационные технологии в науке, управлении, социальной сфере и медицине»/ Часть II / под ред. О.Г.Берестневой, О.М.Гергет; Национальный исследовательский Томский политехнический университет. − Томск: Изд-во Томского политехнического университета, 2017. − 397 с.
  6. Гасумова, С.Е. Информационные технологии в социальной сфере: Учебное пособие для бакалавров / С.Е. Гасумова. - М.: Дашков и К, 2015. - 312 c.
  7. Громов Ю.Ю. Информационные технологии : учебник / Ю. Ю. Громов, И. В. Дидрих, О. Г. Иванова, М. А. Ивановский, В. Г. Однолько. – Тамбов: Изд-во ФГБОУ ВПО «ТГТУ», 2015. – 260 с.
  8. Демьянова О.В. Информационные технологии // Проблемы современной экономики. – 2018. − №1 (33).
  9. Информационные системы и технологии: Научное издание. / Под ред. Ю.Ф. Тельнова. - М.: ЮНИТИ, 2016. - 303 c.
  10. Каткова Л.А. Информационно-технологическое перевооружение системы управления предприятием как фактор повышения конкурентоспособности предприятия. // Теория и практика общественного развития. – 2017.- №8.
  11. Корнеев, И.К. Информационные технологии в работе с документами: Учебник / И.К. Корнеев. - М.: Проспект, 2015. - 304 c.
  12. Котова В. А. Теоретические и методические основы реструктуризации бизнес модели промышленного предприятия: предпроектная стадия: Дисс. канд. экон. наук: 08.00.05/ Самарский. гос. эконом. ун-т. – С.: РГБ, 2016 — С. 171.
  13. Круглова О.В. Информационные технологии в управлении: учебное пособие. - Дзержинск: изд-во «Конкорд», 2016. – 134 с.
  14. Лбов Г.С., Полякова Г.Л. Информационные технологии в современном бизнесе // Вестник Сибирского государственного аэрокосмического университета имени академика М.Ф. Решетнева. – Красноярск, 2017. - Т.31- №5. - С. 42-45.
  15. Логинов, В.Н. Информационные технологии в государственном и муниципальном управлении: учебное пособие. -М: из-во КНОРУС, 2013. -240с.
  16. Максимов, Н.В. Современные информационные технологии: Учебное пособие / Н.В. Максимов, Т.Л. Партыка, И.И. Попов. - М.: Форум, 2018. - 512 c.
  17. Мамонова, Т.Е. Информационные технологии. лабораторный практикум: Учебное пособие для прикладного бакалавриата / Т.Е. Мамонова. - Люберцы: Юрайт, 2016. - 176 c.
  18. Маркова В.Д. Информационные технологии: сущность и инновационная составляющая // Проблемы современной экономики. – 2016. – № 21. – С. 38-42.
  19. Матушевская, Е.Г. Информационные технологии управления (для бакалавров) / Е.Г. Матушевская, А.Т. Рахманова. - М.: КноРус, 2017. - 240 c.
  20. Микрюков, В.Ю. Информационные технологии в государственном и муниципальном управлении / В.Ю. Микрюков. - М.: КноРус, 2017. - 248 c.
  21. Наумов А.А., Бах С.А. Информационная среда. Синтез, анализ, моделирование и оптимизация. - Новосибирск: «ОФСЕТ», 2017. – 307 с.
    Репин В.В., Елиферов В.Г. Процессный подход к управлению. Моделирование бизнес-процессов. – М. РИА «Стандарты и качество», 2015. – 408 с.
  22. Тельнов Ю. Ф. Интеллектуальные информационные системы. М.: МЭСИ, 2015.
  23. Титоренко Г.А. Информационные технологии в маркетинге : учебник / Под ред. Г. А. Титоренко. — М.: ЮНИТИ-ДАНА, 2016. — 335 с.
  24. Тихонов Э.Е. Информационные технологии в управлении: учебное пособие. — Ставрополь: Изд-во СКФУ, 2015. – 402 с.
  25. Федосеева Н.Н. Сущность и проблемы электронного документооборота в информационных технологиях // Юрист. – 2017. – №6. – С.61.
  26. Щипицина, Л.Ю. Информационные технологии в лингвистике: Учебное пособие / Л.Ю. Щипицина. - М.: Флинта, 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