Добавить в цитаты Настройки чтения

Страница 183 из 372

            MessageBox (NULL, pszText, "Publication",

            MB OK|MB SETFOREGROUND);

           free(pszText);

           }

          // Удаление всех публикаций

               if(nNewID)

                for(int id = 0; id < nNewID; id++)

           {

                 aIPub[id] — > Release ();

            }

            SysFreeString(bstr);

            CoUninitialize (); // Завершение работы с COM

            return 0;

}

Несколько замечаний к приведенной программе.

СОМ функция CoGetClassObject имеет следующие параметры:

• Ссылка на идентификатор создаваемого кокласса

• Тип запрашиваемого сервера CLSCTX_INPROC_SERVER означает, что запрашивается сервер в процессе клиента. Дня локального сервера надо задать СLSСТX_LОСAL_SЕRVER, и для удаленного — CLSCTX_REMOTE_SERVER. Можно комбинировать эти флаги для автоматического выбора наиболее близкого сервера.

• В третьем параметре задается информация об удаленной машине при использовании удаленного сервера.

• Идентификатор запрашиваемого интерфейса

• Возвращаемый указатель на запрашиваемый интерфейс

Функция MessageBox() используется для вывода информации о публикации в окне сообщений. Эту информация клиент получает с сервера вызывав метод GetInfо(). Память под возвращаемую BSTR-строку сервер выделяет сам, а клиент отвечает за ее освобождение. Перед передачей информации в окно сообщений выполняется преобразование BSTR-строки в ANSI-строку.

Язык описания интерфейсов и библиотека типов

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

Первое означает, что как компоненты, так и использующие их клиенты могут реализовываться на любом поддерживающем СОМ языке программирования (в частности, C++ и Visual Basic). Однако описанные ранее интерфейсы (файлы IPub.h, IBook.h и IJoumal.h) представлены на C++. Это означает, что любой разработчик, желающий реализовать эти интерфейсы в своем коклассе, должен использовать именно C++. Более неприятно, что и любой клиент, желающий использовать построенные таким образом компоненты, также должен быть написан на C++.

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

Что нужно для обеспечения независимости от языка и прозрачности местоположения? Нужно описать все интерфейсы и классы некоторым стандартным образом, сделав эти описания доступными компиляторам со всех языков, поддерживающих СОМ. Это и обеспечит языковую независимость. Дня обеспечения прозрачности местоположения нужно иметь возможность автоматически формировать посредников, обеспечивающих взаимодействие клиента и сервера, выполняющихся в различных процессах. В СОМ такой посредник на стороне клиента называется прокси, а посредник на стороне сервера называется заглушкой. Они реализуются в виде компонент, загружаемых в адресные пространства клиента и сервера и обеспечивают для последних иллюзию непосредственного взаимодействия друг с другом (в одном адресном пространстве). В действительности прокси и заглушка реализуют удаленный вызов процедур, используя протокол LRPC или RPC соответственно при расположении на одной или различных машинах.

Итак, C++ не годится для описания интерфейсов в связи с тем, что в этом языке много неоднозначностей, которые, конечно, успешно разрешаются компилятором с C++, но в которых не смогут разобраться компиляторы с других языков. Нужен специальный язык, на котором можно однозначно описать все интерфейсы и классы. Это язык описания интерфейсов IDL–Interface Definition Language, первоначально описанный в спецификации DCE (Distributed Computing Environment — распределенная среда вычислений) от Open Software Foundation и далее расширенный Microsoft. На нем описываются все коклассы и все реализуемые в них интерфейсы, которые будут входить в создаваемый компонент. При этом нет необходимости описывать ранее описанные интерфейсы (например, стандартные). Достаточно включить их описания с помощью ключевого слова import. Наряду с описанием коклассов и интерфейсов надо описать так называемую библиотеку типов. Именно эта библиотека и будет решать проблему языковой независимости. Она будет в бинарном виде хранить информацию о всех интерфейсах и классах данного компонента в форме, доступной для чтения компиляторами со всех поддерживающих СОМ языков.

Далее idl-файл с описанием интерфейсов, классов и библиотеки типов транслируется транслятором MILD (Microsoft IDL) в совокупность файлов, содержащих объявления на С++/С всех интерфейсов, определения GUID для всех интерфейсов и классов, коды прокси и заглушки, а также формируется в бинарном виде библиотека типов. Используя эти файлы можно построить dll для прокси и заглушки. При реализации клиента или сервера на С++/С можно использовать полученные файлы с описаниями интерфейсов и определениями GUID, при использовании других языков программирования, будет использоваться библиотека типов.

Далее приведен файл PubinProcServerTypeInfo.idi, дающий описания на IDL интерфейсов, классов и библиотеки типов для проекта PubInProcServer.

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 IJournal: 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.