Такой сервер, если он не реализует интерфейс IMarshall, может работать лишь в одной «комнате» с клиентом, поэтому его следует использовать только для In-Process-серверов с потоковой моделью, идентичной клиенту.
При создании сервера, не включающего библиотеку типов, необходимо указать мастеру реализуемые им интерфейсы. Укажем имя интерфейса ITest. По завершении работы мастера будет создан следующий модуль:
unit Unit1; interface uses Windows, ActiveX, Classes, ComObj; type TTest = class(TComObject, ITest) protected end; const Class_Test: TGUID = '{1302FB00-703F-11D4-84DD-825B45DBA617}'; implementation uses ComServ; initialization TComObjectFactory.Create(ComServer, TTest, Class_Test, 'Test', '', ciMultiInstance, tmApartment); end.Внимание! COM-сервер, который может использоваться различными клиентами (а не только в рамках конкретного проекта, в котором спецификации клиентов жестко заданы), не рекомендуется создавать без поддержки маршалинга данных, поскольку в этом случае невозможно обеспечить гарантированное нахождение его в одной «комнате» с клиентом. Если вы все же делаете такой сервер, в документации на него необходимо отразить требуемые спецификации клиента. |
Рассмотрим сгенерированный код подробнее. Особый интерес представляет секция Initialization. В ней создается экземпляр «фабрики объектов» — COM-сервера, реализующего интерфейс IClassFactory2. К нему COM будет обращаться для создания экземпляра объекта Test. VCL автоматически выполняет всю рутинную работу по взаимодействию с COM.
Для реализации сервера требуется написать интерфейсный модуль с описанием реализуемого интерфейса. Кроме того, вынесем в него описание константы Class_Test и добавим его в строку uses модуля Unit1:
unit TestInterface; interface const Class_Test: TGUID = '{1302FB00-703F-11D4-84DD-825B45DBA617}'; type ITest = interface ['{1C986802-6D6D-11D4-84DD-996A491CE716}'] procedure ShowIt(S: String); end; implementation end.Этот модуль содержит всю необходимую информацию для работы сервера и должен использоваться при компиляции клиента.
Дополним код COM-объекта реализацией методов реализуемого интерфейса:
unit Unit1; interface uses Windows, ActiveX, Classes, ComObj, TestInterface; type TTest = class(TComObject, ITest) protected procedure ShowIt(S: String); end; implementation uses ComServ; { TTest } procedure TTest.ShowIt(S: String); begin MessageBox(0, PChar(S), NIL, 0); end; initialization TComObjectFactory.Create(ComServer, TTest, Class_Test, 'Test', '', ciMultiInstance, tmApartment); end.Откомпилировав проект, мы получим файл Project1.dll.
Последним шагом является регистрация COM-сервера.
Введем в командной строке «regsvr32 project1.dll».
Если все было проделано правильно, на экране должно появиться сообщение об успешной регистрации: «DllRegisterServer in Project1.dll succeeded».
Теперь можно приступать к написанию клиента. Для этого создадим новый проект, добавим в модуль с его главной формой строку uses TestInterface и напишем следующий код:
uses TestInterface, ComObj; procedure TForm1.Button1Click(Sender: TObject); var Test: ITest; begin Test := CreateComObject(Class_Test) as ITest; Test.ShowIt('Hi'); end;Как видно из этого примера, создание и использование COM-сервера не сложнее, чем работа с обычными классами Delphi. Сервер без библиотеки типов является хорошим выбором для реализации COM-серверов, используемых внутри проекта, поскольку для его работы нужен интерфейсный модуль. При передаче сервера другим разработчикам вам придется передать им этот модуль и при необходимости перевести его на другой язык (например, С).