«Машины должны работать. Люди должны думать»
46. Последовательность событий при обращении клиента к серверу COM
Шаг 1. |
Клиентское приложение запрашивает интерфейс путем вызова конструктора сокласса. Сокласс является производным от класса TObject и содержит только два конструктора и больше никаких методов. Конструктор Create используется для внутрипроцессных или локальных серверов, а CreateRemote – для серверов, размещенных на удаленных компьютерах. Любой из этих конструкторов должен создать экземпляр объекта и возвратить указатель на первый интерфейс (интерфейс по умолчанию), предоставляемый COM объектом. В Delphi конструктор сокласса вызывает метод CreateComObject (для локального сервера) или CreateRemoteComObject (для удаленного сервера). В свою очередь метод CreateComObject вызывает функцию Win API CoCreateInstance (или CoCreateInstanceEx в случае удаленного сервера). Вот реализация метода CreateComObject в модуле ComObject: Function CreateComObject(const ClassID: TGUID): IUnknown; Begin OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result)); End; Функция-оболочка OleCheck предназначена для генерации исключительной ситуации в случае ошибки – и только. Главный параметр обсуждаемых функций – это идентификатор сокласса ClassID, который идентифицирует в реестре Windows библиотеку (или приложение), содержащую реализацию сервера. Вот содержимое ветви реестра HKEY_CLASSES_ROOT\CLSID\ для зарегистрированного внутрипроцессного сервера: [{40BC0668-D946-11D5-BE01-ABCDCE4D71F9}] ="SmpCOM Object" InprocServer32="D:\WORKDIR\SIMPLECOM\SIMPLECOM.DLL" InprocServer32\"ThreadingModel"="Apartment" ProgID="SimpleCOM.SmpCOM" Version="1.0" TypeLib="{40BC0665-D946-11D5-BE01-ABCDCE4D71F9}" Первый GUID – это и есть идентификатор сокласса. Соответствующую константу (типа TGUID) Delphi по умолчанию именует с префиксом CLASS_, например, CLASS_SmpCOM. |
Шаг 2. |
Функция CoCreateInstance иницирует библиотеку COM, которая по идентификатору CLSID отыскивает в реестре библиотеку .dll (или приложение) и загружает ее в память |
Шаг 3. |
Создается экземпляр объекта фабрика класса. Для случая реализации сервера в виде библиотеки в ее секции инициализации содержится вызов конструктора класса TTypedComObjectFactory (для сервера с библиотекой типов) или TComObjectFactory (для сервера без библиотеки типов). Если сервер реализован в виде библиотеки, то вызов этого конструктора делается в секции инициализации библиотеки. Конструктор класса TTypedComObjectFactory в конечном итоге вызвает унаследованный конструктор класса TComObjectFactory. Параметры конструкторов определяют вид COM сервера и модель его функционирования |
Шаг 4. |
Конструктор сокласса создает COM объект и возвращает указатель на запрошенный интерфейс. Теперь клиентское приложение может вызывать методы интерфейса или, с помощью метода QueryInterface, может получить указатель на любой другой интерфейс, поддерживаемый объектом, по его идентификатору GUID |
Шаг 5. |
Объект COM самостоятельно ведет подсчет ссылок на его интерфейсы. Когда число этих ссылок равно нулю, COM объект уничтожается самостоятельно. Библиотека (или приложение) выгружается из памяти службами COM с помощью функции Win API CoFreeUnusedLibraries. Эта функция выгружает библиотеку с COM объектом в том случае, если функция DllCanUnloadNow возвращает значение S_OK. Реализация библиотеки сервера в соответствии со спецификацией COM должна экспортировать, в общем случае, всего 4 функции: DllGetClassObject, DllCanUnloadNow, DllRegisterServer и DllUnregisterServer |
«45. Составляющие приложений COM»
47. Способы реализации СОМ серверов