Как работают СОМ-серверы Созданный
MY__ISAY_INTERFACE
#pragma once
//====== Для того, чтобы были доступны COM API
#include <windows.h>
//====== Для того, чтобы был виден lUnknown
#include <initguid.h>
// Интерфейс ISay мы собираемся зарегистрировать и
// показать миру. Он, как и положено, происходит от
// IUnknown и содержит чисто виртуальные функции
interface ISay : public lUnknown
{
//=== 2 метода, которые интерфейс
//=== предоставляет своим клиентам
virtual HRESULT _stdcall Say 0=0;
virtual HRESULT _stdcall SetWord (BSTR word)=0;
}
#endif
Абстрактный интерфейс не может жить сам по себе. Он должен иметь класс-оболочку (wrapper class), который на деле реализует виртуальные методы Say и SetWord. Этот так называемый ко-класс (класс СОМ-компонента) производится от интерфейса ISay и предоставляет тела всем унаследованным (чисто) виртуальным методам своего родителя. Так как у интерфейса ISay, в свою очередь, имеется родитель (lUnknown), то класс должен также дать реальные тела всем трем методам IUnknown.
Для того чтобы быть доступным тем приложениям, которые захотят воспользоваться услугами СОМ-объекта, сам класс тоже должен иметь дом (в виде inproc-сервера DLL). Сейчас, разрабатывая проект типа Win32 DLL, мы строим именно этот дом. С помощью механизма DLL класс будет доступен приложению-клиенту, в адресное пространство процесса которого он загружается. Вы знаете, что DLL загружается в пространство клиента только при необходимости.
Нам неоднократно понадобятся услуги инструмента Studio.Net под именем GuidGen, поэтому целесообразно ввести в меню Tools (Инструментальные средства) Studio.Net новую команду для его запуска. GuidGen, так же как и UuidGen, умеет генерировать уникальные 128-битовые идентификаторы, но при этом он использует удобный Windows-интерфейс. А идентификаторы понадобятся нам для регистрации сервера и класса CoSay. Для введения новой команды:
// {170368DO-85BE-43af-AE71-053F506657A2}
DEFINE_GUID («name»,
0xl70368d0, 0x85be, 0x43af, 0xae, 0x71, 0x5, Ox3f, 0x50,
0x66, 0x57, Oxa2);
Замените аргумент «name» на HD_ISay. Повторите всю процедуру и создайте идентификатор для ко-класса CoSay, который вставьте сразу за идентификатором интерфейса ISay. На сей раз замените аргумент «name» на CLSiD_CoSay, например:
// {9B865820-2FFA-lld5-98B4-OOE0293F01B2}
DEFINE_GUID(CLSID_CoSay,
0х9b865820, 0x2ffa, 0xlldS, 0x98, 0xb4, 0x0, 0xe0, 0x29,
0x3f, 0xl, 0xb2);
Сохраните и закройте файл interfaces.h, так как мы больше не будем вносить в него изменений. Если вы хотите знать, что делает макроподстановка DEFINE_GUID, то за ней стоит такое определение:
#define DEFINE_GUID
(name, 1, wl, w2, \ b1, b2, bЗ, b4, b5, b6, b7, b8) \ EXTERN_C
const GUID name \
= { 1, wl, w2, { b1, b2, bЗ,b4, b5, b6, b7, b8 } }
Оно означает, что макрос создает структуру с именем <name> типа GUID, которая служит для хранения уникальных идентификаторов СОМ-объектов, интерфейсов, библиотек типов и других реалий причудливого мира СОМ.