Модель программирования Component Object Model. Разработка COM-сервера, страница 3

Так как у интерфейса ISay, в свою очередь, имеется родитель (IUnknown), то класс должен также дать реальные тела всем трем его методам. Реализуя интерфейс IUnknown, обычный объект C++ превращается в COM-сервер. Интерфейс IUnknown определен в системе как простой абстрактный класс, в котором присутствуют 3 метода: QueryInterface, AddRef и Release. Он используется для двух целей:

¨  Управление жизненным циклом объекта в памяти.

¨  Доступ к интерфейсам.

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

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

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

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

Если вы хотите, чтобы класс реализовывал несколько интерфейсов, то вы должны использовать множественное наследование. Такой подход проповедует ATL (Active Template Library). MFC реализует другой подход к реализации интерфейсов. Он использует вложенные классы. Каждому интерфейсу соответствует новый класс, вложенный в один общий класс COM-объекта.

Абстрактный класс (каковым является наш интерфейс ISay), всегда является базовым классом, который наследуется конкретным классом реализации. Класс реализации может быть:

¨  Классом самого COM-сервера.

¨  Самостоятельным классом, который просто используется COM-сервером.

Для того, чтобы быть доступным тем приложениям, которые захотят воспользоваться услугами COM-объекта, ко-класс тоже должен иметь дом (в виде inproc-сервера DLL). Сейчас, разрабатывая проект типа Win32 DLL, мы строим именно этот дом. С помощью механизма DLL класс будет доступен приложению-клиенту. DLL загружается в адресное пространство клиентского процесса и это делается только при необходимости.

Каждому создаваемому COM-серверу необходимо присвоить GUID (Globally Unique ID – полностью индивидуальный идентификатор). GUID представляет собой 128-битовое уникальное число. Библиотеки OLE используют эти числа, чтобы идентифицировать, получать доступ и обращаться к серверу. GUID COM-сервера называется идентификатором класса (CLSID – class ID). CLSID идентифицирует отдельную реализацию COM-сервера в OLE, то есть это уникальное имя сервера.

Нам неоднократно понадобятся услуги инструмента студии под именем GuidGen. Утилита GuidGen (так же как и UuidGen) умеет генерировать уникальные 128-битовые идентификаторы, но она, в отличие от UuidGen, использует удобный Windows-интерфейс. Идентификаторы типа GUID понадобятся нам для регистрации класса CoSay, а впоследствии и самого сервера (то есть COM-DLL).

Целесообразно проверить есть ли команда запуска утилиты в меню Tools студии. Откройте меню и посмотрите, есть ли в нем команда Create GUID. Если нет, то выполните следующие действия:

1.  Дайте команду Tools4External Tools и в окне диалога External Tools нажмите кнопку Add;

2.  Введите имя новой команды меню Create GUID, переведите фокус в поле Command и нажмите кнопку справа от нее;

3.  С помощью диалога поиска файла, найдите файл Guidgen.exe, который находится в папке ..\Microsoft Visual Studio.NET\Common7\Tools, и нажмите кнопку Open;