Основы COM. Рудалев В.Г - 9 стр.

UptoLike

9
Очень похоже на работу с обычными объектами . Компонентный класс («со -
класс» ) CoEditSrv объявлен в библиотеке типов . Его конструктор Create
возвращает ссылку на интерфейс ICalcSrv и содержит в себе строку
Result := CreateComObject (CLASS_CalcSrv) as ICalcSrv;
Поэтому данный способ полностью эквивалентен способу , рассмотренному в
примере 1.
По завершении работы с COM-объектом клиент освобождает ссылку на него,
что приводит к вызову метода Release. В этот момент COM-сервер проверяет,
есть ли еще ссылки на созданные им объекты . Если все объекты из внешнего
сервера освобождены , то COM-сервер завершает свою работу . Если все объек-
ты из DLL освобождены , то она выгружается из памяти .
Компилятор Delphi автоматически вставляет вызовы методов подсчета ссылок
_AddRef при обращении к интерфейсу и _Release при завершении модуля,
где объявлена переменная интерфейсного типа . Поэтому явное обращение к
ним нарушит подсчет ссылок и вызовет исключительную ситуацию.
1.4. IDispatch и Автоматизация
Рассмотренные нами интерфейсы , основанные на виртуальных таблицах, реа -
лизуют т.н. раннее связывание имен методов с их программной реализацией .
Термин «раннее связывание» здесь несколько отличается от знакомого Вам на
первых курсах , будучи относительным. Оно означает замену компоновщиком
программы (или компилятором, если операции компиляции и компоновки со -
вмещены ) имен методов не на их адреса в программе, а на смещения внутри
виртуальной таблицы . Однако встречаются ситуации, когда и такое связывание
затруднительно или не представляется возможным. Например, у пользователя
компонента может отсутствовать библиотека типов с описанием интерфейсов ,
необходимых компилятору для получения вышеупомянутых смещений. Вызов
COM-объектов часто осуществляется из программ, написанных на языках ин-
терпретируемого типа или на скриптовых языках (например, VBasic или
JScript). В этих случаях разрешение имен должно выполняться без участия
компилятора во время выполнения программы (позднее связывание).
Для решения этой проблемы Microsoft был разработан специальный интерфейс
IDispatch, являющийся основой технологии OLE Automation (Автоматиза-
ция).
Объявление интерфейса IDispatch имеет вид
type
IDispatch = interface (IUnknown)
['{00020400-0000-0000-C000-000000000046}']
function GetTypeInfoCount(out Count: Integer): HRe-
sult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer;
out TypeInfo): HResult; stdcall;
                                            9
О чень похож е на работу с обы чны ми объектами . К омпонентны й класс («со-
класс» ) CoEditSrv объяв лен в би бли отеке ти пов . Е го конструкторCreate
в оз в ращ аетссы лку на и нтерфей сICalcSrv и сод ерж и тв себестроку
Result := CreateComObject (CLASS_CalcSrv) as ICalcSrv;
Поэтому д анны й способ полностью экв и в алентен способу, рассмотренному в
при мере1.
По з ав ерш ени и работы с COM-объектом кли ент осв обож д ает ссы лку на него,
что при в од и т кв ы з ов у метод а Release. В этот момент COM-серверпров еряет,
есть ли ещ е ссы лки на соз д анны е и м объекты . Е сли в се объекты и з в неш него
серв ера осв обож д ены , то COM-серверз ав ерш ает св ою работу. Е сли в се объек-
ты и з DLL осв обож д ены , то она в ы груж аетсяи з памяти .
К омпи ляторDelphi ав томати чески в став ляетв ы з ов ы метод ов под счета ссы лок
_AddRef при обращ ени и ки нтерфей су и _Release при з ав ерш ени и мод уля,
гд е объяв лена переменная и нтерфей сного ти па. Поэтому яв ное обращ ени е к
ни м наруш и тпод счетссы локи в ы з ов ети склю чи тельную си туаци ю .
1.4. IDispatch и А в т о   м ат и заци я
Рассмотренны е нами и нтерфей сы , основ анны е на в и ртуальны х табли цах, реа-
ли з ую т т.н. ранне е св язы в ани е и мен метод ов с и х программной реали з аци ей .
Т ерми н «раннее св яз ы в ани е» з д есь несколько отли чается от з накомого В ам на
первы х курсах, буд учи относи тельны м. О но оз начает з амену компонов щ и ком
программы (и ли компи лятором, если операци и компи ляци и и компонов ки со-
в мещ ены ) и мен метод ов не на и х ад реса в программе, а на сме ще ни я в нутри
в и ртуальной таб ли цы . О д нако в стречаю тсяси туаци и , когд а и такоесв яз ы в ани е
з атруд ни тельно и ли не пред став ляется в оз мож ны м. Н апри мер, у польз ов ателя
компонента мож ет отсутств ов ать би бли отека ти пов с опи сани ем и нтерфей сов ,
необход и мы х компи лятору д ля получени я в ы ш еупомянуты х смещ ени й . В ы з ов
COM-объектов часто осущ еств ляется и з программ, напи санны х на яз ы ках и н-
терпрети руемого ти па и ли на скри птов ы х яз ы ках (напри мер, VBasic и ли
JScript). В эти х случаях раз реш ени е и мен д олж но в ы полняться без участи я
компи лятора в о в ремяв ы полнени япрограммы (п оздне е св язы в ани е ).
Д ля реш ени я этой проблемы Microsoft бы л раз работан специ альны й и нтерфей с
IDispatch, яв ляю щ и й ся основ ой технологи и OLE Automation (А в томати з а-
ци я).
О бъяв лени еи нтерфей са IDispatch и меетв и д

type
  IDispatch = interface (IUnknown)
     ['{00020400-0000-0000-C000-000000000046}']
     function GetTypeInfoCount(out Count: Integer): HRe-
     sult; stdcall;
     function GetTypeInfo(Index, LocaleID: Integer;
                       out TypeInfo): HResult; stdcall;