wcstombs(buff, bstr, MAX_NAME_LENGTH); cout << buff << " взорвалась! " << endl << endl; SysFreeString(bstr);
// Освобождаем все полученные интерфейсы, чтобы удалить СоСаr if(pUnk) pUnk->Release();
if(pIEngine) pIEngine->Release(); if(pStats) pStats->Release(); if(pICreateCar) pICreateCar->Release();
СоСаr пока еще не является бинарным (исполняемым) объектом, годным для повторного использования. Чтобы достичь этой цели, нам необходимо познакомиться с фабриками класса и хранилищами объектов.
Контрольные вопросы
1.Каково назначение методов интерфейса IUnknown?
2.Назовите правила применения этих методов.
3.Что значит «создание объекта»?
4.Как создаются объекты в модели COM?
5.Для чего применяется GUID?
34
Практическое занятие № 5 Разработка (внутрипроцессного) сервера распределённого
приложения для Windows на С++
Цель практического занятия Изучить и освоить разработку внутрипроцессного сер-
вера распределённого приложения для Windows, получить практические навыки по разработке сетевых программ на языках С, С++.
Теоретические сведения:
Будет разработан первый настоящий СОМ-сервер. Возьмем класс СоСаr, разработанный дома, и создадим фабрику класса для активизации его по запросу клиента. Также поместим новые объекты в Win32 DLL, реализуем экспорт
(DllGetciassObject() и DllCanUnloadNow()) и соз-
дадим регистрационный файл для внесения CОM-информации в реестр системы. Пример проекта находится в каталоге … \Сh3\CarInProcServ3-2
1. Подготовка рабочего пространства проекта и перенос
СоСаr
Начнем с создания нового пустого рабочего пространства проекта Win32 DLL с именем СarInProcServer (рис. 3).
Добавьте новый файл с именем CarInProcServer.cpp. Объявите две глобальных переменных типа ulong для счетчика блокировок и счетчика объектов. Убедитесь, что новый файл вставлен в рабочее пространство проекта:
#include <windows.h>
//Количество блокировок сервера
ULONG g_lockCount =0;
//Количество "живых" объектов в сервере
ULONG g_objCount =0;
35
Рис. 3. Новый проект Win32 DLL
Кокласс CоСаr и соответствующие интерфейсы, определенные в предыдущей работе, легко переносятся и в этот проект. Скопируйте следующие файлы из каталога прошлой работы в текущий каталог данной работы:
СoСar.h и СoCar.cpp - кокласс Car; iid.h и iid.cpp - файлы GUIP;
interfaces.h - пользовательские интерфейсы. Вставьте файлы *,срр в пространство проекта (с помо-
щью Project | Add To Project | Files...) и откомпилируйте. За-
головочные файлы вручную можно не включать, т. к. они вставляются автоматически.
Поскольку данная версия CоCаr будет размещена в двоичном файле, нам потребуется CLSID для уникальной идентификации CоCаr в среде СОМ. Сгенерируйте новый GUID (с помощью guidgen.exe), кoторый станет CLSID для CоCаr.Определите константу CLSID_CoCar в качестве первого параметра макроса define_guid. Добавьте этот GUID в ваш существующий файл iid.h.
36
Чтобы закончить перенос исходного кода, нужно реализовать увеличение и уменьшение глобального счетчика объектов в конструкторе и деструкторе класса СоСаr. Мы должны информировать DLL-сервер о том, сколько объектов на данный момент «живут» в нем. Используйте ключевое слово extern для обращения к глобальной переменной g_objCount внутри класса СоСаr:
// CоCаr.срр
extern ULONG g_objCount;
СоСаr::СоСаr() : m_refCount(0), m_currSpeed(0), m_maxSpeed(0) { ++g_objCount; // Прочий код...
}
СоСаг::~CoCar()
{
--g_objCount; // Прочий код...
}
IDE поместил все файлы *.h в каталог External Dependencies окна FileView и определения интерфейсов не показываются в ClassView. Можно перенести их в каталог Header Files, после чего интерфейсы станут видимыми из
ClassView (рис. 4).
Рис. 4. Исправленный ClassView.
37
2. Разработка фабрики класса для СоСаr
Для создания СоСаr понадобится фабрика класса. Вставьте новый класс с именем coCarClassFactory, производный от IClassFactory. Вспомните, что объект класса обеспечивает языково-независимый способ создания объектов СОМ. Вот начальное определение объекта класса:
#include <windows.h>
class CoCarClassFactory:public IClassFactory
{
public:
CoCarClassFactory();
virtual ~CoCarClassFactory(); // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** piFace); STDMETHODIMP_(ULONG)AddRef(); STDMETHODIMP_(ULONG)Release();
// IClassFactory
STDMETHODIMP LockServer(BOOL fLock); STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppv);
private:
ULONG m_refCount; // Устанавливается в нуль в конструкторе!
};
Начнем c реализации методов IUnknown, AddRef(), Release() и QueryInterfасе().
Код почти полностью совпадает с реализацией IUnknown для СоСаr, за исключением того, что на этот раз QueryInterfасе о проверяет только IID_IUnknown и IID_IClassFactory:
// Реализация IUnknown в фабрике класса
STDMETHODIMP_(ULONG) CoCarClassFactory::AddRef()
{
return ++m_refCount;
38