Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Роджерсон Д. - Основы COM - 2000.pdf
Скачиваний:
412
Добавлен:
13.08.2013
Размер:
2.4 Mб
Скачать

104

после компиляции и компоновки файла CMPNT.DLL. Как пояснялось в предыдущей главе, REGSVR32.EXE вызывает функцию DllRegisterServer, т. е. фактически выполняет регистрацию клиента. Если Вы не запускали make-файл, этот шаг Вам придется сделать самостоятельно. Для удобства я привожу командный файл REGISTER.BAT, состоящий из одной этой команды. Аналогичные файлы для выполнения регистрации прилагаются и к примерам следующих глав.

DllMain

Чтобы получить имя файла DLL и зарегистрировать его, функции DllRegisterServer нужен описатель содержащей ее DLL. Этот описатель передается функции DllMain. В программах на C++ есть функция main, с которой начинается выполнение. Программы для Windows используют WinMain, а DLL — DllMain. Реализовать DllMain для получения описателя модуля DLL нетрудно:

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

{

if (dwReason == DLL_PROCESS_ATTACH)

{

g_hModule = hModule;

}

return TRUE;

}

Эта функция заносит описатель в глобальную переменную g_hModule, откуда его могут считать функции

DllRegisterServer и DllUnregisterServer.

Несколько компонентов в одной DLL

Я уже говорил выше, что DllGetClassObject позволяет нам поддерживать несколько компонентов в одной DLL. Ключевой момент здесь — передача DllGetClassObject CLSID создаваемого компонента. Для каждого CLSID DllGetClassObject легко может создать особую фабрику класса (см. рис. 7-3).

Клиент

 

 

 

 

 

DLL

ВызываетCoCreateInstance

 

 

DllGetClassObject

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Фабрика класса 1

 

 

 

 

 

 

 

 

Фабрика класса n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Компонент 1

 

 

 

 

 

 

 

 

Компонент n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 7-3 Одна DLL может содержать несколько компонентов

Тот факт, что DLL может поддерживать много разных компонентов, — одна из причин, по которым DLL соответствует не компоненту, но серверу компонентов. Концепция DLL, предоставляющей клиенту компоненты по запросу, очень мощна. DLL — это средство распространения реализаций компонентов.

Повторное применение реализации фабрики класса

Если Вы похожи на меня, то Вы терпеть не можете писать один и тот же код снова и снова. Необходимость иметь CFactory1, CFactory2 и CFactory3, которые будут снова и снова реализовывать один и тот же код для создания компонентов CA, CB и CC, кажется излишней. В нашем случае в этих разных фабриках класса различались бы только следующие строки:

CA* pA = new CA; pA->QueryInterface(...);

Если Вы правильно спроектировали свою фабрику класса и компоненты, то Вам понадобится только одна реализация фабрики для всех компонентов. Я предпочитаю для каждого компонента создавать по одной простой функции. Эта функция создает компонент при помощи операции new и возвращает указатель на IUnknown. Затем я строю из указателей на эти функции таблицу, индексируемую CLSID каждого компонента. DllGetClassObject просто отыскивает в таблице указатель нужной функции, создает фабрику класса и передает ей этот указатель. Затем, вместо того, чтобы непосредственно использовать операцию new, фабрика класса при помощи указателя вызывает соответствующую функцию создания компонента (см. рис. 7-4).

Соседние файлы в предмете Программирование на C++