интерфейсного заместителя. Администратор заглушек вызывает метод CreateStub с целью создания новой интерфейсной заглушки.

Когда в объекте запрашивается новый интерфейс, то администраторы заместителей и заглушек должны преобразовать запрошенные IID и CLSID интерфейсного маршалера. Под Windows NT 5.0 хранилише класса совершает эти преобразования в директории NT, и они кэшируются в локальном реестре каждой хост-машины. Отображения IID в CLSID всей машины кэшируются в

HKEY_CLASSES_ROOTInterface

а отображения каждого пользователя кэшируются в

HKEY_CURRENT_USERSoftwareClassesInterface

Один из этих ключей или оба будут содержать подключи для каждого известного интерфейса. Под Windows NT 4.0 и в более ранних версиях не существует хранилища классов и используется только область локального реестра HKEY_CLASSES_ROOTInterface.

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

[HKCRInterface{1A3A29F0-D87E-11d0-8C4F-0080C73925BA}]

@='IRacer'

[HKCRInterface{1A3A29F0-D87E-11d0-8C4F-OB80C73925BA}ProxyStubClsid32]

@='{1A3A29F3-D87E-lld0-8C4F-0080C73925BA}'

Эти элементы реестра означают, что существует внутрипроцессный сервер с CLSID, равным {1A3A29F3-D87E-11d0-8C4F-0080C73925BA}, который реализует интерфейсные заместитель и заглушку для интерфейса IRacer ({1A3A29F0-D87E-11d0-8C4F-0080C73925BA}). Из этого следует, что HKCRCLSID будет иметь подключ для интерфейсного маршалера, отображающего CLSID в соответствующее имя файла DLL. Опять же под Windows NT 5.0 это отображение может содержаться в хранилище классов, которое способно динамически заполнять локальный реестр. Поскольку интерфейсный маршалер должен выполняться в том же апартаменте, что и администратор заместителей или администратор заглушек, они должны использовать (флаг) ThreadingModel=&quotBoth' для гарантии того, что они всегда могут загрузиться в нужный апартамент.

Реализация интерфейсных маршалеров

В предыдущем разделе было показано четыре интерфейса, используемых архитектурой стандартного маршалинга. Хотя и допустимо реализовать интерфейсные маршалеры с помощью ручного кодирования на C++, на практике это осуществляется редко. Дело в том, что компилятор IDL может автоматически генерировать исходный С-код для интерфейсного маршалера на основе IDL-определения интерфейса. Созданные MIDL интерфейсные маршалеры преобразуют параметры метода в последовательную форму, используя протокол Сетевого Представления Данных (Network Data Representation – NDR), который допускает демаршалинг этих параметров при различных архитектурах хост-машин. NDR учитывает различия в порядке следования байтов, в формате с плавающей точкой, в наборе символов и в расположении результатов. NDR поддерживает фактически все совместимые с C типы данных. Для того чтобы обеспечить передачу интерфейсных указателей как параметров, MIDL генерирует вызовы CoMarshalInterface / CoUnmarshalInterface для маршалинга любых параметров интерфейсных указателей. Если параметр является статически типизированным интерфейсным указателем:

HRESULT Method([out] IRacer **ppRacer);

то сгенерированный код маршалера будет маршалировать параметр ppRacer путем передачи IID IRacer (IID_IRacer) вызовам CoMarshalInterface / CoUnmarshalInterface . Если же интерфейсный указатель типизирован динамически:

HRESULT Method([in] REFIID riid, [out, iid_is(riid)] void **ppv);

то сгенерированный код маршалера будет маршалировать интерфейс, используя IID, переданный динамически в первый параметр метода.

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

// sports.idl

// виды спорта. Язык описания интерфейсов

[local, object] interface IBoxer : IUnknown { … }

[object] interface IRacer : IUnknown { … }

[object] interface ISwimmer : IUnknown { … }

[helpstring(«Sports Lib»)]

library SportsLibrary {

interface IRacer;

// include def. of IRacer in TLB

// включаем определение IRacer в библиотеку типов TLB

[object] interface IWrestler : IUnknown { … } }

только интерфейсы IRacer и ISwimmer будут иметь исходный код интерфейсного маршалера. MIDL не будет генерировать маршалирующий код для IBoxer, поскольку атрибут [local] подавляет маршалинг. MIDL также не будет генерировать маршалер для IWrestler, поскольку он определен внутри области действия библиотечного оператора.

Если MIDL представлен в IDL такого типа, он будет генерировать пять файлов. Файл sports.h будет содержать С/С++-определения интерфейсов, sports_i.с – IID и LIBID, a sports.tlb – разобранный (tokenized) IDL для IRacer и IWrestler , который можно использовать в средах разработки, поддерживающих СОМ. Файл sports_p.c будет содержать фактические реализации методов интерфейсных заместителей и заглушек, которые осуществляют преобразования вызова методов в NDR. Этот файл также может содержать С-определения виртуальной таблицы (vtable) для интерфейсных заместителей и заглушек наряду со специальным управляющим кодом MIDL. Поскольку интерфейсные маршалеры являются внутрипроцессными серверами СОМ, то четыре стандартные точки входа (DllGetClassObject и другие) должны быть также определены. Эти четыре метода определены в пятом файле dlldata.c.

Для того чтобы построить интерфейсный маршалер из этих сгенерированных файлов, необходимо

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату