Назначение и принципы COM-технологии. Объявление интерфейсов и их использование при создании приложений

   
На этом шаге мы рассмотрим, как объявляются интерфейсы.

   
Для реализации интерфейсов в Delphi имеются эксперты, которые выполняют
для программиста черновую работу по реализации интерфейсов, необходимых для работы соответствующих
СОМ-объектов - COM Object, Automation Object, ActiveX Control и Property Page.
С некоторыми из них мы познакомились на 2 и 3 шагах.
Соответствующие эксперты вызываются при выполнении команды File | New | Other... | ActiveX, и далее
производится выбор типа создаваемого объекта из репозитария объектов.


Рис.1. Репозитарий объектов

   
Создание интерфейса начинается с его объявления. Интерфейсы объявляются с помощью зарезервированного слова
interface. Например:

type
  IMyData=interface(IUnknown)
     procedure GetMyData(var N:integer);
     procedure SetMyData(N:integer); 
  end;

   
Данный пример объявляет новый интерфейс IMyData. К существующим методам IUnknown добавляются
методы GetMyData и SetMyData. Если предком данного интерфейса является IUnknown, то
в объявлении разрешается опускать имя предка - в данном случае легальна запись:
IMyData=interface - без указания предка. То же самое можно сделать и при объявлении нового
класса, если предком является TObject.

   
Если данный пример поместить в какой-либо проект, то проект может быть скомпилирован и запущен
без какой-либо реализации методов GetMyData и SetMyData. Это еще раз подтверждает
тот факт, что все методы интерфейсов являются абстрактными и не требуют реализации.

   
Выше приведенное объявление интерфейса вполне легально, если он будет использоваться внутри одного
модуля. Но интерфейс, как он объявлен в данном примере, не может быть экспортирован в другие
модули и из других модулей нельзя получить указатель на данный интерфейс. Причина - импорт
и экспорт интерфейса осуществляется через GUID. Объявление с назначением GUID выглядит
следующим образом:

type
  IMyDataExport=interface(IMyData)
    ['{3C7EAEDE-7C59-11D2-AC74-00605207DE1D}']
    {One can insert additional methods here}
 end;

   
Данное объявление определяет интерфейс со всеми методами IMyData и IUnknown, но
добавляет к нему GUID. Для экспорта интерфейса, помимо GUID, необходимо создать
и зарегистрировать фабрику класса. GUID для нового интерфейса должен быть уникальным
и генерироваться в соответствии с алгоритмом, определенным Open System Foundation.
Для его генерации можно самостоятельно создать небольшое приложение, где вызывается метод CoCreateGUID:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ActiveX;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
   GUID:TGUID;
   S:String;
begin
  if CoCreateGuid(GUID)=S_OK then
      Edit1.Text:=GUIDToString(GUID);
end;

end.

Текст этого приложения можно взять оператора AS
с интерфейсами. При его применении компилятор Delphi генерирует код, который вызывает метод
QueryInterface. В качестве параметра метода QueryInterface применяется GUID.
Поэтому оператор AS можно легально использовать только с интерфейсами, в которых был
определен IID, и, следовательно, зарегистрированными в системном реестре и имеющими фабрику
класса:

procedure TForm1.AnotherUseDataExport(const IU:IUnknown);
var
   N:integer;
   DE:IMyDataExport;
begin
  if Assigned(DE) then 
  begin 
    DE:=IU as IMyDataExport;
    DE.GetMyData(N);
    Caption:=IntToStr(N);
  end;
end;

   
Код выше является легальным и работоспособным. Строка

    DE:=IU as IMyDataExport;

полностью эквивалентна строке

    if IU.QueryInterface(IMyDataExport,DE)<>S_OK then raise EOLEError.Create...

   
Но при попытке использовать интерфейс IMyData вместо IMyDataExport
в примере выше:

procedure TForm1.AnotherUseDataExport(const IU:IUnknown);
var
   N:integer;
   DE:IMyDataExport;
begin
  if Assigned(DE) then 
  begin 
    DE:=IU as IMyData;
    DE.GetMyData(N);
    Caption:=IntToStr(N);
  end;
end;

компилятор Delphi остановится на выделенной строке с диагнозом:
Operator not applicable to this operand type - оператор неприменим к данным.
Причина - отсутствие IID у интерфейса IMyData.

   
На следующем шаге мы рассмотрим реализацию интерфейсов.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий