import "oaidl.idl";
//IPub
[obj ect,
uuid(9A5DE9A0-7225-11d5-98C7-000001223694),
helpstring("Base publication")]
interface IPub: IUnknown
{
HRESULT SetTitle([in] BSTR bstrTitle);
HRESULT SetYear([in] int nYear);
HRESULT Getlnfo([out, retval] BSTR* pbstrlnfo);
};
//IBook
[object,
uuid(9A5DE9A1-7225-11d5-98C7-000001223694),
helpstring("Book")]
interface IBook: IPub
{
HRESULT SetAuthor([in] BSTR bstrAuthor);
}
//IJournal
[object,
uuid(9A5DE9A2-7225-11d5-98C7-000001223694),
helpstring("Journal")]
interface IJournaclass="underline" IPub
{
HRESULT SetNumber([in] int nNumber);
}
[uuid(68A702C2-8283-11d5-98C7-000001223694),
version(1.0),
helpstring("PubinProcServer with TypeLib")]
library PubinProcServer
{
importlib("stdole32.tlb");
[uuid(49F00760-7238-11d5-98C7-000001223694)]
coclass CoBook
{
[default] interface IBook;
{;
[uuid(49F00761-7238-11d5-98C7-000001223694)]
coclass CoJournal
{
[default] interface IJournal;
};
};
Видно, что данный файл весьма похож на заголовочный файл в C++. Основное отличие — наличие атрибутов в квадратных скобках.
Конструкция import "oaidi. idi"; обеспечивает импорт ряда стандартных описаний (в том числе, интерфейса IUnknown). Далее идут описания всех реализуемых в компоненте пользовательских интерфейсов: IPub, IBook и IJournal.
Описанию каждого интерфейса предшествует совокупность атрибутов, начинающаяся с атрибута object. Именно этот атрибут говорит о том, что далее идет описание интерфейса СОМ, а не интерфейса RPC, для описаний которых и создавался первоначально IDL.
Атрибут uuid используется для задания GUID соответствующего интерфейса.
Атрибут helpstring позволяет приписать описываемому интерфейсу некоторую строку, которая будет храниться в библиотеке типов и может использоваться различными программами для представления пользователю информации о семантике данного интерфейса.
При описании методов интерфейсов используются атрибуты in, out, retval, позволяющие указать направление передачи значения параметра. Атрибут in назначается по умолчанию и означает, что значение данного параметра передается серверу. Напротив, атрибут out говорит о необходимости передачи значения параметра клиенту. Атрибут retval означает, что для данный параметр является возвращаемым значением для соответствующей функции при использовании, например, Visual Basic. Указание этих атрибутов (возможны их сочетания) оптимизирует трафик в сети при выполнении удаленного вызова процедур.
После описания всех интерфейсов описывается библиотека типов (ключевое слово library). В качестве атрибутов для библиотеки типов задаются уникальный идентификатор (GUID, который можно получить с помощью guidgen.exe), номер версии и helpstring.
Оператор importlib ("stdole32.tlb") должен быть первым среди всех операторов библиотеки. Он задает импорт стандартной двоичной библиотеки типов stdole32.tlb.
Далее описываются все коклассы, включаемые в данный компонент. Для каждого кокласса с помощью атрибута uuid задается его GUID и перечисляются все его интерфейсы (последние в иерархии интерфейсов). Один из интерфейсов каждого кокласса объявляется как интерфейс по умолчанию (с помощью атрибута default). Это необходимо для Visual Basic. При инициализации экземпляра данного класса именно ссылка на интерфейс по умолчанию будет возвращена клиенту. При отсутствии атрибута default, интерфейсом по умолчанию становится первый интерфейс в списке интерфейсов данного кокласса.
В данном примере отражены далеко не все возможности языка IDL и некоторые из них будут обсуждены далее. А сейчас рассмотрим использование сформированного idl-файла.
Добавим файл PubInProcServerTypeInfo.idl В проект PubInProcServer и откомпилируем. В результате будут получены несколько файлов. Для сервера в процессе клиента, который мы реализуем в данное время, прокси и заглушка не нужны. В связи с этим включим в проект из всех файлов, сгенерированных транслятором MILD, только PubInProcServerTypeInfo.h, содержащий определения всех интерфейсов на С++/С, и файл PubInProcServerTypeInfo_i.с, содержащий определения уникальных идентификаторов для всех интерфейсов и коклассов.
Далее надо модифицировать часть файлов проекта. Прежде всего из проекта удаляются все ранее использовавшиеся файлы, определявшие интерфейсы и GUID. Это файлы IPub.h, IBook,h, IJournal.h, iid.h, iid.cpp. Во всех оставшихся файлах надо удалить ссылки на удаленные файлы. В файлы CоBооk.h, CоJournal.h надо добавить строку
#include "PubInProcServerTypeInfo.h"
Аналогичные изменения необходимо сделать в клиенте CoPubClient.
Последнее действие — добавление новых данных в реестр. Именно, надо зарегистрировать библиотеку типов — PubInProcServerTypeInfo.tlb. Для этого в реестр системы необходимо внести следующую информацию:
• Под ключом HKEY_CLASSES_ROOT TypeLib надо создать раздел
{68A702C2-8283-11d5-98C7-000001223694} — GUID библиотеки ТИПОВ.
• Для нового раздела создать подраздел 1.0 — номер версии. В качестве значения параметра по умолчанию можно взять название компонента — PubInProcServer.
• Для только что созданного раздела 1.0 создать подраздел 0 — идентификатор языка (естественного).
• Для только что созданного раздела 0 создать 3 подраздела:
♦ Win32 — в качестве значения параметра по умолчанию надо указать путь к библиотеке типов (к файлу PubInProcServerTypeInfo.tlb)
♦ FLAGS — значение параметра по умолчанию ''0"
♦ HELPSTRING — значение параметра по умолчанию — путь к файлу помощи (если таковой имеется)
• И последнее, ссылку на библиотеку типов надо разместить под ключами
НКЕY_CLASSЕS_ROOT CLSID {49F00760-7238-11d5-98С7-000001223694} и
НКЕY_CLASSЕS_ROOT CLSID {49F00761-7238-11d5-98C7-000001223694}.
Для этого под указанными ключами создаются разделы TypeLib, где в качестве значения параметра по умолчанию указывается GUID библиотеки типов для компонента, в котором размещены оба класса.
Теперь компонент, созданные в проекте PubInProcServer, включает библиотеку типов PubInPrосServerTуреInfj.tlb и, следовательно, может использоваться клиентами, реализованными на других языках, поддерживающих СОМ. Например, в Visual Basic достаточно установить ссылку на библиотеку типов нашего компонента и можно создавать экземпляры коклассов CоBооk и CоJournal, получая по умолчанию ссылки на интерфейсы IBook и IJournal.
Для проверки того, что сформированная библиотека типов PubInPrосServerTуреInfj.tlb действительно содержит всю информацию, содержавшуюся ранее в idl-файле PubIinProcServerTypeInfo.idl, можно воспользоваться OLE/COM Object Viewer, С ПОМОЩЬЮ которого МОЖНО увидеть все классы ИЗ компонента PubinProcServer, их интерфейсы, методы этих интерфейсов и их сигнатуры.