1 / 45

Інтерфейси COM. Інкапсуляція COM - об'єктів у Delphi

Інтерфейси COM. Інкапсуляція COM - об'єктів у Delphi. 2003. ( Курс “Інформаційні технології” ). Зміст. Інтерфейси COM -об’єкти та інтерфейс IUnknown Об’єкти автоматизації та інтерфейс IDispatch Зв'язування: пізнє, раннє, dispinterface- зв'язування.

tana-booker
Download Presentation

Інтерфейси COM. Інкапсуляція COM - об'єктів у Delphi

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Інтерфейси COM.Інкапсуляція COM- об'єктів у Delphi 2003 (Курс “Інформаційні технології”)

  2. Зміст • Інтерфейси • COM-об’єкти та інтерфейс IUnknown • Об’єкти автоматизації та інтерфейс IDispatch • Зв'язування: пізнє, раннє, dispinterface-зв'язування. • Динамічні запити. Двоїсті інтерфейси • Фабрики класів та інтерфейс IClassFactory • Інтерфейси та спряжені класи • Бібліотеки типів Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  3. Визначення інтерфейсів (інтерфейсних типів) в ObjectPascal за формою нагадують визначення об'єктів (класів), але при цьому використовується ключове слово interface. Зокрема, можна створювати ієрархії інтерфейсів (відповідно до традиційного принципу успадкування один інтерфейс може визначатися на основі іншого). Водночас є істотні відмінності між класом і інтерфейсом. Інтерфейси та особливості їх визначення в Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  4. В інтерфейсі специфікуються тільки функціональні можливості (procedure, function, property). (Поля відсутні взагалі, їх наявність привела б до втрати гнучкості в реалізації COM-серверів). Кожний інтерфейс повинен успадковуватись (безпосередньо чи опосередковано) від інтерфейсу IUnknown. Традиційно імена інтерфейсів починаються з літери I. Для інтерфейса не треба описувати секцію реалізації. Клієнту через інтерфейс надається інформація про функціональність COM-об’єкта. А як відповідна функціональність реалізується, клієнту не важливо - це справа розробника COM-сервера. По суті усі методи інтерфейсів є абстрактними, проте директива abstract не повинна вказуватись. Також по суті методи інтерфейсів є віртуальними, але й директиву virtual не треба вказувати. Нарешті, не треба вказувати для інтерфейса і директиву обмеження області видимості, хоча де-факто вона завжди відповідає public. Примірники інтерфейсів ніколи не створюються. Доступ до інтерфейса (та його методів) здійснюється через вказівник на інтерфейс і стає можливим тільки після створення спряженого з інтерфейсом COM-об’єкта. Відмінності між класами та інтерфейсами Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  5. Приклад класу TNewClass із реалізованими в ньому двома інтерфейсами – IIntfl та IIntf2): IIntfl=interface(IUnknown) ['{СD113D61-548F-101B-8E65-08002B2BD119}'] ProcedureMethod; safecall; end; IIntf2=interface(IUnknown) ['{СD113D62-548F-101B-8E65-08002B2BD119}'] ProcedureMethod; safecall; end; TNewClass = class(TClass1, IIntfl, IIntf2) (* механізм перейменування*) ProcedureIIntfl.Method=Method1; ProcedureIIntf2.Method=Method2; ProcedureMethod1; ProcedureMethod2; . . . end; Клас з кількома інтерфейсами. Проблема конфлікту імен Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  6. Інтерфейси (COM-інтерфейси), як уже відзначалося, - це засіб специфікації функціональності об’єкта, яка є доступною "зовні" (для "зовнішнього користувача", наприклад, для програми-клієнта). COM-об’єкт - це об’єкт (у термінології ООП), що підтримує (реалізує) хоча б один інтерфейс. Але, виходячи з особливостей призначення й використання COM-об’єктів, останні мусять бути наділеними деякими властивостями, грубо кажучи, від свого народження. Саме з цих позицій визначається інтерфейс IUnknown і COM-об’єкти уточнюються як такі, що мають підтримувати цей інтерфейс. Отже, можна запропонувати формулу: COM-об’єкт = об’єкт + IUnknown + . . . Відповідно всі COM-інтерфейси мають успадковуватись (прямо або опосередковано) від IUnknown. COM-об’єкти та їх інкапсуляція в Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  7. Методи IUnknown: QueryInterface…; AddRef; Release. Інтерфейс IUnknown забезпечує для COM-об'єктів дві дуже важливі можливості: управління часом життя об'єкта: AddRef і Release використовуються для підрахункунаявних посилань (reference count) на об'єкт, і коли число посилань дорівнюватиме нулю, об'єкт вивантажуватиметься з пам'яті; навігацію серед множини інтерфейсів об'єкта за допомогою функції QueryInterface. Функція QueryInterfасе дозволяє, по-перше, з'ясувати, чи підтримується об'єктом той чи інший інтерфейс (він задається параметром), і, по-друге, якщо інтерфейс підтримується, то визначається і повертається вказівник на цей інтерфейс (також через параметр). Інтерфейс IUnknown Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  8. У Delphi функція QueryInterface реалізується у спосіб: functionQueryInterface(constIID: TGUID; outObj): Integer; begin ifGetInterface(IID, Obj) thenResult := S_OKelseResult := E_NOINTERFACE; end; (GetInterface є класовим (class) методом TObject). Приклад. Нехай деякий об'єкт підтримує інтерфейси I1 та I2, і є вказівник (P1) на інтерфейс I1 цього об'єкта. Тоді в результаті виклику P1.QueryInterface(I2,P2) P2 буде повертати вказівник на інтерфейс I2 об'єкта. Інтерфейс IUnknown. Функція QueryInterface Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  9. СистемаВерсія1 ------- інструментарій1(InterfaceFirstFirm) СистемаВерсія2 ------- інструментарій2(InterfaceFirstFirm, InterfaceSecondFirm) СистемаВерсія1 + інструментарій2 ? СистемаВерсія2 + інструментарій1 ?(QueryInterface ------ Menu) СистемаВерсія3 ------- інструментарій3(InterfaceFirstFirm, InterfaceFirstFirm2, InterfaceSecondFirm) (принцип незмінності інтерфейсів) QueryInterface та підтримка версій незалежних розробників Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  10. Delphi спрощує підтримування вимог, пов’язаних із інтерфейсом IUnknown: 1. Програмісту не треба піклуватися про підрахунок посилань. Цей підрахунок забезпечується для згенерованих у DelphiCOM-об'єктів автоматично. 2. Для отримування вказівника на інший інтерфейс (I2) можна скористатись більш зручним (у порівнянні з QueryInterface) засобом - оператором as. Наприклад, якщо точно відомо, що Оbj1 підтримує інтерфейс I2, то для отримання вказівника на цей інтерфейс можна використати оператор: P2:= Obj1asI2. (Якщо об'єктом Оbj1 інтерфейс I2 не підтримується, при виконанні цього оператора буде виникати виняткова ситуація). У сумнівних щодо підтримки інтерфейсу випадках краще використовувати безпосередньо class-метод TObject.GetInterface: ifObj1.GetInterface(I2, P2) then { усе гаразд! } Інтерфейс IUnknown. Специфіка Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  11. Інтерфейс IUnknown у Delphi (модуль System) описується наступним чином: IUnknown = interface ['{00000000-0000-0000-C000-000000000046}'] functionQueryInterface(constIID: TGUID; outObj): Integer; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; Символ підкреслювання “_” в ідентифікаторах _AddRef і _Release слід розглядати як свого роду попередження про те, що ці методи користувачу не слід викликати напряму, оскільки, нагадуємо, підрахунок посилань на COM-об'єкти в Delphi відбувається автоматично. Опис інтерфейса IUnknown у Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  12. Усі притаманні COM-об’єктам властивості в мові ObjectPascal інкапсульовані в класі TComObject, який визначається наступним чином: TComObject=class(TObject,IUnknown,ISupportErrorInfo). Разом з інтерфейсом IUnknown, як видно, TComObject підтримує ще один інтерфейс – інтерфейс ISupportErrorInfo. Інтерфейс ISupportErrorInfo має лише одну функцію: ISupportErrorInfo = interface(IUnknown) ['{DF0B3D60-548F-101B-8E65-08002B2BD119}'] functionInterfaceSupportsErrorInfo(constiid: TIID): HResult; stdcall; end. Інкапсуляція COM-об’єктів у Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  13. Інтерфейс ISupportErrorlnfo використовують додатки, що одержують інформацію про помилки. Він дозволяє переконатися, що інформація про помилку коректно передається по всьому можливому ланцюжку викликів. Зокрема, цей інтерфейс має реалізовуватись в об'єктах автоматизації, що використовують інтерфейси обробки помилок. Реалізація InterfaceSupportsErrorInfo у класі TComObject: functionTComObject.InterfaceSupportsErrorInfo (constiid: TIID): HResult; begin ifGetInterfaceEntry(iid) <> nil then Result := S_OKelse Result := S_FALSE; end. Інкапсуляція COM-об’єктів у Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  14. Функція TObject.GetInterfaceEntry є класовою (class-) функцією і повертає “вхід” інтерфейса (у випадках, коли інтерфейс реалізований у класі): classfunctionGetInterfaceEntry(constIID:TGUID): PInterfaceEntry. Тип PInterfaceEntry описується таким чином: PInterfaceEntry = ^TInterfaceEntry; TInterfaceEntry = record IID: TGUID; VTable: Pointer; IOffset: Integer; end; Інкапсуляція COM-об’єктів у Delphi (продовження) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  15. Об’єкти автоматизації є поняттям, що пов'язують із технологією автоматизації – Automation (рання назва OLEAutomation). Автоматизація – це механізм автоматичного управління (в одній програмі – програмі-контролері) об’єктами (об’єктами автоматизації) з іншої програми – програми-сервера автоматизації. З наведеного означення, на жаль, не можливо помітити різницю між поняттями COM-об'єктів та об'єктів автоматизації. Є й інші тлумачення. Часто об'єктами автоматизації просто вважають COM-об'єкти, що підтримують інтерфейс IDispatch: об’єкт автоматизації= COM-об’єкт + IDispatch+ . . . Але і таке визначення не бездоганне. Дійсно, інтерфейс IDispatch відіграє важливу роль у забезпеченні можливостей механізму автоматизації, зокрема у випадках так званого пізнього зв’язування. Проте реалізація автоматизації не завжди вимагає підтримки цього інтерфейсу, наприклад, у випадках, що відповідають ранньому зв’язуванню (таке зв’язування можливе для об'єктів автоматизації, що створюються, наприклад, в середовищі Delphi чи С++). Історично технологія автоматизації розроблялась перш за все з орієнтацією на рідне дітище Microsoft – VisualBasic (в якому не має повної підтримки ООП) та на макромови програм-додатків на зразокVBA. У таких випадках, дійсно, автоматизація не може обійтись без IDispatch. Об’єкти автоматизації Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  16. У Delphi властивості об’єктів автоматизації інкапсульовані в класі TAutoObject. Означення класу TAutoObject відбувається у такій послідовності: { COMobjectwithtypeinformation } TTypedComObject = class(TComObject, IProvideClassInfo) protected { IProvideClassInfo } functionGetClassInfo(outTypeInfo: ITypeInfo): HResult; stdcall; end; (Інтерфейс ITypeInfo містить методи, що забезпечують видобування з бібліотеки типів даних про інтерфейси, про методи таких інтерфейсів тощо). { OLEAutomationobject } TAutoObject = class(TTypedComObject, IDispatch) Об’єкти автоматизації та їх інкапсуляція в Delphi Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  17. Варто зауважити, що в середовищі Delphi програмування автоматизації не потребує безпосереднього використання методів інтерфейсу IDispatch, оскільки в Delphiавтоматизаціяінкапсулюється в цілому. (Згадаймо хоча б уже наведені конкретні приклади на використання автоматизації). Однак розуміння, наприклад, механізму пізнього зв'язування, а саме воно використовувалося в усіх прикладах, що розглядалися, не можливе без залучення понять, пов'язаних із методами IDispatch. Об’єкти автоматизації та їх інкапсуляція в Delphi (продовження) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  18. Пізнє зв'язування (latebinding) є зв'язуванням на етапі виконання програми (а не на етапі компіляції). Наведемо фрагмент, що вже використовувався: varV:Variant; . . . V := CreateOleObject('word.basic'); V.AppShow; Виклик метода AppShow не може бути не тільки відтрансльований, але навіть синтаксично проконтрольований. Так, із тим же успіхом транслятор “проковтне” оператор V.Abracadabra (можна добавляти тут і скільки завгодно параметрів). Пізнє зв'язування Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  19. Насправді, з V.AppShow спряжені наступні дії (користувач про них може і не здогадуватись): 1) Спочатку здійснюється виклик метода GetIDsOfNames. Він дозволяє за іменем AppShow (іменем метода об’єкта автоматизації) одержати відповідний числовий ідентифікатор диспетчеризації – DispId. (При наявності параметрів для кожного з них також обчислюється DispId. Це плата за можливість використання схем викликів з необов'язковими параметрами, на зразок V.TextToTable(ConvertFrom := 1, // 1 - tab char; 2 - "," NumColumns := countP, Format := 16); // варіант з можливих в AutoFormat) 2) Далі викликається Invoke. Йому, зокрема, передається DispId метода (обчислений на кроці 1 з використанням метода GetIDsOfNames) та вказівник на масив аргументів. І саме Invoke ініціює виконання того метода об’єкта автоматизації, що відповідає DispId. Механізм пізнього зв'язування Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  20. Інтерфейс IDispatch описується у Delphi (модуль System) так: IDispatch = interface(IUnknown) ['{00020400-0000-0000-C000-000000000046}'] functionGetTypeInfoCount(outCount: Integer): Integer; stdcall; functionGetTypeInfo(Index, LocaleID: Integer; outTypeInfo): Integer; stdcall; functionGetIDsOfNames(constIID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): Integer; stdcall; functionInvoke(DispID: Integer; constIID: TGUID; LocaleID: Integer; Flags: Word; varParams; VarResult, ExcepInfo, ArgErr: Pointer): Integer; stdcall; end; Інтерфейс IDispatch Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  21. varV:Variant; . . . V := CreateOleObject('word.basic'); V.AppShow; _________________________ var Serv: variant; V: OleVariant; . . . Serv:=CreateOleObject('SMarsh.Marsh') . . . Serv.GetData(V); Динамічні виклики Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  22. var (* модульClient_d3 *) IDis:IDispatch; WMethodName: WideString; PMethodName: PWideChar; DispID: Integer; OleArgs: array of OleVariant; DispIDList: TDispIDList; P_DispIDList: PDispIDList ; DispParams: TDispParams; varGUID: TGUID; reslt:variant; IDis := CreateOleObject('serv_3.d3') as IDispatch; Інтерфейс IDispatch та динамічні виклики Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  23. WMethodName := 'f1'; PMethodName := PWideChar(WMethodName); varGUID:=StringToGUID('{0AC34292-F30A-4046-B8DC-FD42B75698BC}'); OLECHECK(IDis.GetIDsOfNames(varGUID, @PMethodName,1,0,@DispID)); OleArgs:=VarArrayCreate([0,0],varVariant); OleArgs[0]:=strtoint(edit1.Text); DispIDList[0]:=0; P_DispIDList:=@DispIDList; FillChar(DispParams, SizeOf(DispParams), 0); DispParams.rgvarg := @OleArgs[0]; // PVariantArgList DispParams.cArgs := 1; // integer DispParams.rgdispidNamedArgs := P_DispIDList; // PDispIDList DispParams.cNamedArgs := 1; // integer OLECHECK(IDis.Invoke(DispID, GUID_NULL, 0, DISPATCH_METHOD{=1}, DispParams, @reslt, @ExcepInfo, @ArgErr)); Label1.Caption:= reslt; Інтерфейс IDispatch та динамічні виклики(фрагмент модуля Client_d3 *) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  24. Динамічні виклики (приклади програм) Запуск Client_din Запуск Cl_p Запуск Client_d3 Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  25. Інтерфейс вважають двоїстим (дуальним) (dual), якщо він дозволяє використовувати як статичні, так і динамічні виклики. Механізм динамічних викликів інкапсульований в інтерфейсі IDispatch, а саме завдяки методам GetIDsOfNames та Invoke. Отже, двоїстими будуть всі інтерфейси, що успадковуються від IDispatch та, зокрема, всі інтерфейси, які генеруються майстром автоматизації (майстром об’єктів автоматизації) Delphi. Фрагмент модуля Pr_Dlg_TLB: IConv_Dlg = interface(IDispatch) ['{EFAF2364-017A-11D8-A3E5-444553540000}'] function Conv(USD: Double): Double; safecall; end; Двоїсті (dual) інтерфейси Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  26. varV:Variant; . . . V := CreateOleObject('word.basic'); (* Модуль ComObj *) function CreateOleObject(const ClassName: string): IDispatch; var ClassID: TCLSID; begin ClassID := ProgIDToClassID(ClassName); OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IDispatch, Result)); end; function CreateComObject(const ClassID: TGUID): IUnknown; begin OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown,Result)); end; Створення COM-об’єктів Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  27. Cтворення COM-об’єктів відбувається за два наступні кроки: 1) COMAPI функція CoCreateInstance(ClassID, . . ., IID, . . .) викликає іншу COMAPI функцію - CoGetClassObject, передаючи їй отриманий ClassID як параметр. (IID для наведених вище прикладів є відповідноIDispatch та IUnknown). CoGetClassObject на основі ClassID та (завжди фіксованого!) IClassFactory дозволяє отримати вказівник на спеціальний об’єкт (знову-таки COM-об’єкт) – так званий “об’єкт типа”, “фабрика класу”, “об’єкт класу”(ClassObject). “Фабрика класу” здатна генерувати екземпляри об’єктів – “об’єкти-екземпляри”. 2) Використовуючи “фабрику класу”, а саме шляхом виклику метода CreateInstance з інтерфейса IClassFactory, буде генеруватись екземпляр об’єкта (при цьому в одному з параметрів повертатиметься вказівник на інтерфейс у відповідності до заданого параметром IID). Механізм створення COM-об’єктів Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  28. uses ComObj, ActiveX, Pr_Dlg_TLB; {$R *.DFM} var V: IConv_Dlg; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption:=floattostr(V.Conv(StrToFloat(edit1.text))); end; procedure TForm1.FormCreate(Sender: TObject); var HRes : HResult; pObFactory : IClassFactory; begin HRes := CoGetClassObject (Class_Conv_Dlg, CLSCTX_SERVER, NIL, IClassFactory, pObFactory); OleCheck (HRes); HRes := pObFactory.CreateInstance (NIL, IConv_Dlg, V); OleCheck (HRes); end; Механізм створення COM-об’єктів (приклад) Cli2_Dlg Client_2_factory\CMarsh Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  29. Технологія COM виходить з концепції об'єкта (COM-об'єкта) "фабрика класів", чия задача – це створення об'єктів автоматизації (COM-об'єктів). Коли програма-сервер запускається, фабрика створюється і публікується в COM ("реєструється" в COM). (Фабрики, як правило, створюються і публікуються в процесі ініціалізації сервера автоматизації). "Реєстрація" у даному випадку не пов’язана із занесенням інформації до системного реєстру. Мається на увазі, що фабрика стає “відомою” COM і може бути використана програмами-клієнтами під час виконання. (Для такої реєстрації є спеціальна COM API функція CoRegisterClassObject). Фабрика дозволяє створювати асоційовані з нею об'єкти (автоматизації/COM) завдяки підтримці інтерфейсу IClassFactory. Створення фабрик класів Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  30. unit Dlg_ObAuto; interface uses ComObj, Pr_Dlg_TLB, StdVcl; type TConv_Dlg = class(TAutoObject, IConv_Dlg) function Conv(USD: Double): Double; safecall; end; implementation uses ComServ, Un_Dlg; function TConv_Dlg.Conv(USD: Double): Double; begin result:= Convert(USD); end; initialization TAutoObjectFactory.Create(ComServer, TConv_Dlg, Class_Conv_Dlg, ciMultiInstance); end. Class_ TConv_Dlg– «дружня» константа для GUID. Таку константу Delphi створює і використовує автоматично. Модуль автоматизації. Створення фабрики класів. Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  31. IClassFactory визначається в такий спосіб: IClassFactory = interface(IUnknown) ['{00000001-0000-0000-C000-000000000046}'] function CreateInstance(const unkOuter: IUnknown; const iid: TIID; out obj): HResult; stdcall; function LockServer(fLock: BOOL): HResult; stdcall; end; Інтерфейс IClassFactory Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  32. IUnknown IUnknown IInt1 IClassFactory Реалізація статичних аспектів класу Реалізація нестатичних аспектів класу Iint2 ClassID COM-об’єкти для ClassID Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  33. Раннє зв'язування (earlybinding) або зв'язування через інтерфейси ґрунтується на тому, що в контролерах автоматизації є відомими інтерфейси об'єкта автоматизації (наприклад, в результаті імпортування бібліотеки типів). У цьому випадку, по-перше, звертання до методів інтерфейсу об'єкта автоматизації можуть перевірятись на коректність передавання параметрів ще на стадії компіляції та, по-друге, контролери автоматизації можуть викликатинапряму методи об'єкта: за вказівником на інтерфейс та іменем метода, використовуючи vtable, одразу при компіляції генерується виклик підпрограми, що реалізує цей метод (без використання методу Invoke). Про об'єкт автоматизації, який дозволяє здійснювати як раннє, так і пізнє зв'язування, говорять, що він підтримуєподвійний (або дуальний) інтерфейс (dual interface). Об'єкти автоматизації, які генеруються майстрами Delphi, завжди підтримують подвійний інтерфейс. Раннє зв'язування Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  34. Так зване зв'язування через диспінтерфейси (dispinterface зв'язування) є зв'язуванням на основі спеціальних інтерфейсів, які ґрунтуються на залученні у визначення таких інтерфейсів диспетчерських ідентифікаторів DispId. Воно займає “проміжне положення” між раннім та пізнім зв'язуваннями. (Іноді саме його називають раннім, але тоді зв'язування за допомогою інтерфейсів вважається надраннім). У цьому випадку ідентифікатори диспетчеризації (DispId) є відомими вже на стадії компіляції і, відповідно, у викликах GetIDsOfNames вже не виникає потреби. Delphi знову-таки стосовно до об'єктів автоматизації, створюваних майстрами, забезпечує повну підтримку зв'язування на основі диспінтерфейсів. Зв'язування через диспінтерфейси Запуск Cli3_Dlg Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  35. Ідентифікатори диспетчеризації (DispId) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  36. Приклади зв'язування: пізнє (variant), раннє (interface), диспінтерфейсами (dispinterface) uses ComObj, Pr_Dlg_TLB; var V:variant; . . . V:= CreateOleObject('Pr_Dlg.Conv_Dlg'); Res:=V.Conv(1.2); var Interf:IConv_Dlg; . . . Interf := CoConv_Dlg.Create; // or Interf := CreateOleObject('Pr_Dlg.Conv_Dlg') as IConv_Dlg; Res:=Interf.Conv(1.2); var DispInterf:IConv_DlgDisp; . . . DispInterf := CoConv_Dlg.Create as IConv_DlgDisp; Res:=DispInterf.Conv(1.2); Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  37. // GUIDS declared in the TypeLibrary. Following prefixes are used: // Type Libraries : LIBID_xxxx // CoClasses : CLASS_xxxx // DISPInterfaces : DIID_xxxx // Non-DISP interfaces: IID_xxxx const LIBID_Pr_Dlg:TGUID='{EFAF2363-017A-11D8-A3E5-444553540000}'; IID_IConv_Dlg:TGUID='{EFAF2364-017A-11D8-A3E5-444553540000}'; CLASS_Conv_Dlg:TGUID='{EFAF2365-017A-11D8-A3E5-444553540000}'; type // Forward declaration of types defined in TypeLibrary IConv_Dlg = interface; IConv_DlgDisp = dispinterface; // Declaration of CoClasses defined in Type Library // (NOTE: Here we map each CoClass to its Default Interface) Conv_Dlg = IConv_Dlg; Фрагменти з модуля Pr_Dlg_TLB (модуль генерується редактором бібліотек типів) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  38. IConv_Dlg = interface(IDispatch) ['{EFAF2364-017A-11D8-A3E5-444553540000}'] function Conv(USD: Double): Double; safecall; end; IConv_DlgDisp = dispinterface ['{EFAF2364-017A-11D8-A3E5-444553540000}'] function Conv(USD: Double): Double; dispid 1; end; (* The Class CoConv_Dlg provides a Create and CreateRemote method to create instances of the default interface IConv_Dlg exposed by the CoClass Conv_Dlg *) CoConv_Dlg = class class function Create: IConv_Dlg; class function CreateRemote(const MachineName: string): IConv_Dlg; end; Фрагменти з модуля Pr_Dlg_TLB (модуль генерується редактором бібліотек типів) (продовження) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  39. implementation uses ComObj; class function CoConv_Dlg.Create: IConv_Dlg; begin Result := CreateComObject(CLASS_Conv_Dlg) as IConv_Dlg; end; class function CoConv_Dlg.CreateRemote(const MachineName: string): IConv_Dlg; begin Result := CreateRemoteComObject(MachineName, CLASS_Conv_Dlg) as IConv_Dlg; end; Фрагменти з модуля Pr_Dlg_TLB (модуль генерується редактором бібліотеки типів) (закінчення) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  40. Бібліотеки типів є засобом вичерпного документування про об'єкти (автоматизації/СОМ), причому засобом, незалежним від мов програмування. Загалом, у бібліотеках типів міститься інформація про інтерфейси, про методи та властивості інтерфейсів (зокрема й диспінтерфейсів), про спряжені до інтерфейсів класи. Бібліотеки типів можуть бути інтегровані у вигляді ресурсу в СОМ-сервери (зокрема, в сервери автоматизації), а також можуть надаватись у вигляді файлів з розширенням tlb. Майстри розробки СОМ-об'єктів (об'єктів автоматизації) Delphi автоматично і додають бібліотеки типів у сервери в якості ресурсів, і створюють відповідні tlb-файли. Більш того, починаючи з п'ятої версії Delphi, майстри при створенні бібліотек типів забезпечують інфраструктуру для можливості генерації компонент. Бібліотеки типів Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  41. З іншого боку, в середовищі Delphi забезпечені можливості ефективного використання бібліотек типів при розробці програм-клієнтів: з програми сервера або з tlb-файлу можна імпортувати бібліотеку типів – створювати відповідний імпортований pas-модуль та, долучаючи його до проекту, використовувати описи СОМ-об'єктів та інтерфейсів як свої "рідні". Імпортування здійснюється у відповідності з використанням кроків: меню ProjectImport Type Library. При імпортуванні також можна (у версіях Delphi, починаючи з п'ятої) обирати опцію щодо додаткового створення компонент з розміщенням їх у з палітрах компонент; у редакторі бібліотек типів можна переглядатиtlb-файли, а також експортувати їх у мову визначення інтерфейсів IDL (кнопка ExporttoIDL редактора). Бібліотеки типів (продовження) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  42. Імпортування бібліотеки типів при розробці контролерів автоматизації забезпечує такі додаткові привабливі можливості: використовувати раннє зв'язування (через інтерфейси); використовувати зв'язування через диспінтерфейси; задіяти автоматичний маршалінг параметрів між клієнтом і сервером (для типів, визначених у бібліотеці типів) – маршалінг здійснюється без будь-яких зусиль як з боку програми-сервера, так і з боку програми-клієнта); використовувати створювані (у версіях Delphi не нижче п'ятої) компоненти для візуального проектування програми-контролера . Переваги від імпортування бібліотеки типів Запуск browser_tlb Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  43. ITypeLib = interface(IUnknown) ['{00020402-0000-0000-C000-000000000046}'] function GetTypeInfoCount: Integer; stdcall; function GetTypeInfo(index: Integer; out tinfo: ITypeInfo): HResult; stdcall; function GetTypeInfoType(index: Integer; out tkind: TTypeKind): HResult; stdcall; function GetTypeInfoOfGuid(const guid: TGUID; out tinfo: ITypeInfo): HResult; stdcall; function GetLibAttr(out ptlibattr:PTLibAttr):HResult;stdcall; function GetTypeComp(out tcomp: ITypeComp): HResult; stdcall; function GetDocumentation(index: Integer; pbstrName: PWideString; pbstrDocString: PWideString; pdwHelpContext: PLongint; pbstrHelpFile: PWideString): HResult; stdcall; function IsName(szNameBuf: POleStr; lHashVal: Longint; out fName: BOOL): HResult; stdcall; function FindName(szNameBuf: POleStr; lHashVal: Longint; rgptinfo: PTypeInfoList; rgmemid: PMemberIDList; out pcFound: Word): HResult; stdcall; procedure ReleaseTLibAttr(ptlibattr: PTLibAttr); stdcall; end; ITypeLib (ActiveX) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  44. ITypeInfo = interface(IUnknown) ['{00020401-0000-0000-C000-000000000046}'] function GetTypeAttr(out ptypeattr: PTypeAttr): HResult; stdcall; function GetTypeComp(out tcomp: ITypeComp): HResult; stdcall; function GetFuncDesc(index: Integer; out pfuncdesc: PFuncDesc): HResult; stdcall; function GetVarDesc(index: Integer; out pvardesc: PVarDesc): HResult; stdcall; function GetNames(memid: TMemberID; rgbstrNames: PBStrList; cMaxNames: Integer; out cNames: Integer): HResult; stdcall; function GetRefTypeOfImplType(index: Integer; out reftype: HRefType): HResult; stdcall; function GetImplTypeFlags(index: Integer; out impltypeflags: Integer): HResult; stdcall; function GetIDsOfNames(rgpszNames: POleStrList; cNames: Integer; rgmemid: PMemberIDList): HResult; stdcall; function Invoke(pvInstance: Pointer; memid: TMemberID; flags: Word; var dispParams: TDispParams; varResult: PVariant; excepInfo: PExcepInfo; argErr: PInteger): HResult; stdcall; ITypeInfo(ActiveX) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

  45. function GetDocumentation(memid: TMemberID; pbstrName: PWideString; pbstrDocString: PWideString; pdwHelpContext: PLongint; pbstrHelpFile: PWideString): HResult; stdcall; function GetDllEntry(memid: TMemberID; invkind: TInvokeKind; bstrDllName, bstrName: PWideString; wOrdinal: PWord): HResult; stdcall; function GetRefTypeInfo(reftype: HRefType; out tinfo: ITypeInfo): HResult;stdcall; function AddressOfMember(memid: TMemberID; invkind: TInvokeKind; out ppv: Pointer): HResult; stdcall; function CreateInstance(const unkOuter: IUnknown; const iid: TIID; out vObj): HResult; stdcall; function GetMops(memid: TMemberID; out bstrMops: WideString): HResult; stdcall; function GetContainingTypeLib(out tlib: ITypeLib; out pindex: Integer): HResult; stdcall; procedure ReleaseTypeAttr(ptypeattr: PTypeAttr); stdcall; procedure ReleaseFuncDesc(pfuncdesc: PFuncDesc); stdcall; procedure ReleaseVarDesc(pvardesc: PVarDesc); stdcall; end; ITypeInfo(ActiveX) (продовження) Інтерфейси COM. Інкапсуляція COM- об'єктів у Delphi

More Related