«Любой дурак может написать программу, которую поймет компилятор. Хорошие программисты пишут программы, которые смогут понять другие программисты»
50. Последовательность создания простого COM объекта в Delphi
В данном разделе рассматривается алгоритм разработки простого COM объекта, реализованного в виде библиотеки DLL, подключаемой к приложению.
Процесс создания COM объекта состоит из следующих этапов:
1. Проектирование COM объекта.
2. Использование мастера Delphi для создания COM объекта.
3. Регистрация COM объекта.
4. Разработка клиентского приложения.
5. Тестирование COM объекта.
Проектирование COM объекта. На этом этапе необходимо выбрать вид используемого интерфейса. Мастер предлагает использование в качестве базового (родительского) любого из нескольких интерфейсов. В данном разделе будет предполагаться выбор предлагаемого по умолчанию интерфейса IUnknown.
Далее необходимо определиться с типом сервера. Для всех типов серверов, кроме удаленных, COM выполняет маршалинг автоматически и без использования библиотеки типов, но для удаленных серверов надо использовать библиотеку типов или самостоятельно выполнять маршалинг. Использование библиотеки типов существенно облегчает разработку СОМ объекта, предоставляя "паскалевский" доступ к методам СОМ объекта
Этап 1. Выполнить тему меню File\New\ActiveX\ActiveX Library, с помощью которой будет создана заготовка проекта, включающего сервер. На этом этапе потребуется только сохранить проект под заданным именем, в данном примере SimpleCOM. В результате будет создан файл проекта (единственный, без модулей) с таким содержимым.
library SimpleCOM;
uses ComServ;
exports
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;
{$R *.RES}
begin
end.
Этап 2. Выполнить тему меню File\New\ActiveX\COM Object для добавления в проект объекта COM. В результате появится диалоговое окно, в котором необходимо задать параметры нового объекта.
Теперь необходимо заполнить поля ввода предлагаемой мастером формы.
Окно COM Object Wizard |
Назначение |
ClassName |
Имя разрабатываемого объекта COM |
Instancing |
Способ создания экземпляра объекта (instancing mode). Возможные значения: internal, single instance и multiplay instance. Если COM объект используется только внутри процесса, значение этого поля игнорируется |
Threading model |
Модель поточной обработки, указывающая на то, как клиентское приложение может обращаться к интерфейсу COM объекта. Эта модель также влияет на то, как объект будет регистрироваться, и на детали его реализации |
Implemented interfaces |
Имя интерфейса – это имя класса с предшествующим символом I. Генерируется мастером автоматически |
Description |
Строка описания класса, используемая при его регистрации |
Include Type Library |
Установка этого режима приводит к включению в проект библиотеки типов – генерации нового интерфейса для класса CoClass. При отключении этого режима этот интерфейс надо разрабатывать самостоятельно |
Mark interface OLEAutomation |
Подключение маршалинга, главным образом для внутрипроцессных серверов. Этот режим может быть включен только при включенном режиме подключения библиотеки типов |
При создании простого СОМ объекта можно оставить все установки, предлагаемые мастером, без изменения, за исключением имени объекта. При выборе имени объекта необходимо учесть, что Delphi автоматически добавит в имя первый символ "Т".
После задания требуемых значений и нажатия кнопки OK появится следующее диалоговое окно редактора библиотеки типов:
Еще до каких-либо установок в этом окне в проект будет добавлен новый модуль, который мы сохраним под именем Main. Исходный код этого модуля следующий:
unit Main;
interface
uses
Windows, ActiveX, Classes, ComObj, SimpleCOM_TLB, StdVcl;
type
TSmpCOM = class(TTypedComObject, ISmpCOM)
protected
{Declare ISmpCOM methods here}
end;
implementation
uses ComServ;
initialization
TTypedComObjectFactory.Create(ComServer, TSmpCOM, Class_SmpCOM,
ciInternal, tmApartment);
end.
Кроме того, будет сгенерирован и добавлен в проект файл с именем SimpleCOM_TLB.pas, который обеспечивает наиболее удобный и простой доступ к интерфейсам и методам СОМ объекта. Наибольший интерес представляют следующие фрагменты кода этого файла:
const
{Глобальные идентификаторы библиотеки типов (LIBID_SimpleCOM), сокласса (CLASS_SmpCOM), интерфейса СОМ объекта (IID_ISmpCOM)}
LIBID_SimpleCOM: TGUID = '{BB10BDEA-D908-11D5-A8B6-00C026266A1F}';
IID_ISmpCOM: TGUID = '{BB10BDEB-D908-11D5-A8B6-00C026266A1F}';
CLASS_SmpCOM: TGUID = '{BB10BDED-D908-11D5-A8B6-00C026266A1F}';
type
ISmpCOM = interface;
SmpCOM = ISmpCOM;
ISmpCOM = interface(IUnknown)
['{BB10BDEB-D908-11D5-A8B6-00C026266A1F}']
end;
{объявление сокласса, предоставляющего методы создания экземпляра СОМ объекта}
CoSmpCOM = class
class function Create: ISmpCOM;
class function CreateRemote(const MachineName: string): ISmpCOM;
end;
Теперь вернемся к диалоговому окну редактора библиотеки типов. Повторный вызов редактора библиотеки типов можно выполнить с помощью команды F12 (Toggle Form/Unit) при активном окне с текстом файла SimpleCOM_TLB.pas. С помощью этого редактора удобнее всего снабдить наш СОМ объект дополнительными (кроме уже имеющегося ISmpCOM) интерфейсами и собственно методами, которые будут реализовать функциональность нашего объекта.
Этап 3. Для добавления новых (функциональных) методов к имеющемуся интерфейсу ISmpCOM требуется выполнить такие действия:
В иерархическом списке в левом окне редактора выбрать интерфейс ISmpCOM и щелкнуть на кнопке New Method в панели инструментов.
Заменить стандартное имя метода Method1 на требуемое, например, Tangent. На странице Parameters необходимо задать тип возвращаемого методом значения, а также имена и типы параметров. На остальных страницах можно все оставить без изменений.
Проделываем ту же последовательность действий для другого метода – Cube.
Щелкаем на кнопке Refresh Implementation для модификации исходных текстов файлов Main.pas и SimpleCOM_TLB.pas.
Файл Main.pas теп ерь стал таким:
unit Main;
interface
uses Windows, ActiveX, Classes, ComObj, SimpleCOM_TLB, StdVcl;
type
TSmpCOM = class(TTypedComObject, ISmpCOM)
protected
{ Declare ISmpCOM methods here }
function Cube(Arg: Double): Double; stdcall;
function Tangent(Angle: Double): Double; stdcall;
end;
implementation
uses ComServ;
function TSmpCOM.Cube(Arg: Double): Double;
begin
{реализация функционального метода}
end;
function TSmpCOM.Tangent(Angle: Double): Double;
begin
{реализация функционального метода}
end;
initialization
{создание объекта "фабрика класса"}
TTypedComObjectFactory.Create(ComServer, TSmpCOM, Class_SmpCOM,
ciInternal, tmApartment);
end.
Если посмотреть на содержимое файла SimpleCOM_TLB.pas, то в нем можно заметить такие изменения:
{В описание класса СОМ объекта добавлены функциональные методы Tangent и Cube}
ISmpCOM = interface(IUnknown)
['{BB10BDEB-D908-11D5-A8B6-00C026266A1F}']
function Tangent(Angle: Double): Double; stdcall;
function Cube(Arg: Double): Double; stdcall;
end;
Эти же методы добавлены и в описание класса TSmpCOM = class(TOleServer).
Этап 4. Добавляем необходимый код в методы Tangent и Cube.
Этап 5. Подобным образом добавляем еще один интерфейс ISmpCOM2 и метод Summa, затем модифицируем исходный код метода Summa. На странице Attributes в окне Parent interface необходимо выбрать IUnknown.
Этап 6. Вновь разработанный интерфейс требуется "привязать" к объекту SmpCOM. Для этого необходимо в левом окне редактора выбрать объект SmpCOM, а в правой части окна редактора – страницу Implements. Щелкаем на списке имеющихся интерфейсов правой кнопкой мыши и выбираем интерфейс ISmpCOM2.
Этап 7. Вновь щелкнем на кнопке Refresh Implementation для модификации исходных текстов файлов Main.pas и SimpleCOM_TLB.pas. Редактируем текст функции Summa. Содержимое файла Main.pas теперь станет таким:
unit Main;
interface
uses
Windows, ActiveX, Classes, ComObj, SimpleCOM_TLB, StdVcl;
type
TSmpCOM = class(TTypedComObject, ISmpCOM, ISmpCOM2)
protected
function Cube(Arg: Double): Double; stdcall;
function Tangent(Angle: Double): Double; stdcall;
procedure Summa(Val1, Val2: Double; out Sum: OleVariant); safecall;
{Declare ISmpCOM methods here}
end;
implementation
uses ComServ;
function TSmpCOM.Cube(Arg: Double): Double;
begin
Result:=Arg*Arg*Arg;
end;
function TSmpCOM.Tangent(Angle: Double): Double;
begin
Result:=Sin(Angle)/Cos(Angle);
end;
procedure TSmpCOM.Summa(Val1, Val2: Double; out Sum: OleVariant);
begin
Sum:=Val1+Val2;
end;
initialization
TTypedComObjectFactory.Create(ComServer, TSmpCOM, Class_SmpCOM,
ciInternal, tmApartment);
end.
Этап 8. Регистрация COM объекта. Последнее, что осталось сделать – это откомпилировать проект и зарегистрировать его в качестве сервера с помощью команды Run\Register ActiveX Server. При этом регистрируется также и библиотека типов, содержимое которой можно просмотреть с помощью OLE View. Альтернативный способ – использование команды tregsvr (MS DOS) или выполнение программы regsvr32.exe Windows.
Тестирование COM объекта. Этот этап зависит от функциональности объекта и состоит в проверке работоспособности методов объекта.
Использование OLE View для получения информации о сервере. После регистрации СОМ сервера информацию о нем можно просмотреть с помощью OLE View. В разделе Object classes/All Objects информация о сервере будет записана под именем, заданным в окне редактора библиотеки типов Help String для сокласса. Таким образом, строка Help String выступает в качестве внешнего имени сокласса (СОМ сервера). В разделе Type Libraries можно найти информацию о библиотеке типов под именем, которое было указано в окне Help String редактора библиотеки типов для библиотеки типов.
«49. Расширения COM»
51. Разработка клиентских приложений