Сущность технологии COM



Классы и серверы - часть 6


Так как СОМ преобразует CLSID в данный файл реализации, то для объявления в СОМ относящихся к серверу объектов класса необходимо использовать определенные стандартные методики. Для сервера, основанного на исполняемой программе, в СОМ предусмотрены явные API-функции для связывания объектов класса с их CLSID. Эти API-функции мы будем подробно обсуждать в главе 6. Для сервера, основанного на DLL, DLL должна экспортировать известную функцию, которая будет вызываться с помощью CoGetClassObject, когда потребуется объект класса. Эту функцию необходимо экспортировать с использованием файла определения модулей, причем она должна иметь следующий вид:

HRESULT DllGetClassObject( [in] REFCLSID rclsid, // which class object? // какой объект класса? [in] REFIID riid, // which interface? // какой интерфейс? [out, iid_is(riid)] void **ppv); // put it here! // разместить его здесь!

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

Рассмотрим сервер, реализующий три класса: Gorilla, Chimp и Orangutan. Сервер, возможно, будет содержать шесть отдельных классов C++: три из них создают экземпляры каждого класса, а другие три — объекты класса для каждого класса. В соответствии с этим сценарием, серверная реализация DllGetClassObject будет выглядеть следующим образом:

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { // define a singleton class object for each class // определяем одноэлементный объект класса // для каждого класса static GorillaClass s_gorillaClass; static OrangutanClass s_orangutanClass; static ChimpClass s_chimpClass; // return interface pointers to known classes // возвращаем указатели интерфейсов известных классов if (rclsid == CLSID_Gorilla) return s_gorillaClass.QueryInterface(riid, ppv); else if (rclsid == CLSID_Orangutan) return s_orangutanClass.QueryInterface(riid, ppv); else if (rclsid == CLSID_Chimp) return s_chimpClass.QueryInterface(riid, ppv); // if we get to here, rclsid is a class we don't implement, // so fail with well-known error code // если мы добрались сюда, то rclsid - это класс, который // мы не реализуем, поэтому сбой с известным кодом ошибки *ppv = 0; return CLASS_E_CLASSNOTAVAILABLE; }




Содержание  Назад  Вперед