reklama

Umíme to s Delphi: 167. díl – pod podkličku modelu COM

Dnešní článek se bude opět zabývat komponentovým modelem COM. Vysvětlíme si, jak COM vlastně funguje a jaká je základní architektura COM aplikací. Pak se podíváme na typickou COM komponentu a řekneme si o ní několik nejdůležitějších informací, třeba že musí vždycky poskytovat rozhraní IUnknown, že rozhraní IUnknown musí vždy poskytovat metodu QueryInterface a řadu dalších.

Zdravím všechny věrné čtenáře u dalšího pokračování našeho seriálu o programování v Delphi. Tématem dnešního článku nemůže být nic jiného než naše oblíbené komponentní technologie. Pojďme si připomenout, co jsme si o nich prozradili dosud.

Takže, pověděli jsme si, co jsou to komponentové technologie a proč se o nich vlastně bavíme. Víme už tedy, že rozhodneme-li se zvolit pro vývoj své aplikace komponentní technologii, velmi zjednodušeně řečeno vlastně „vyskládáme“ svou aplikaci ze vzájemně nezávislých komponent. Co to ony komponenty jsou? Softwarová komponenta je definována jako softwarový element, který odpovídá komponentovému modelu, může být nezávisle šířen a může se skládat s ostatními komponentami podle definovaného kompozičního standardu bez jakýchkoliv změn.

Komponentový model pak definuje specifické interakce mezi komponentami a kompoziční standardy. Implementace komponentového modelu je specializovaná množina spustitelných softwarových elementů vyžadovaná k podpoře spouštění komponent odpovídajících tomuto modelu.

Poté jsme se zabývali výhodami komponentních technologií. Pověděli jsme si o pěti bodech, jež bývají uváděny jako největší plusy komponentních technologií:

  • vývoj aplikace nekončí jejím přeložením,
  • aplikace jsou přizpůsobitelnější,
  • existence knihoven komponent,
  • distribuované komponenty,
  • jazyková nezávislost komponent.

Zmínili jsme si také požadavky na komponenty. Existuje jich celá řada, zmiňovány bývají především ty následující:

  • dynamické připojování,
  • skrývání detailů o implementaci,
  • možnost vícenásobného použití,
  • jednoznačná identifikace komponenty,
  • existence mechanismu rozhraní,
  • anonymita klienta,
  • rekurzivní skládání komponent

Před týdnem jsme si povídali o tom, jaké komponentové modely existují, a potomjsme se konečně začali zabývat jedním z nich - komponentovým modelem COM dodávaným firmou Microsoft. Začali jsme velmi zvolna historií toho, jak technologie COM spatřily světlo světa a co jim vlastně předcházelo.

COM – co to vlastně je?

Když jsem zvažoval, jak vlastně technologii COM srozumitelně popsat, měl jsem poměrně velké dilema. K tomu, abych COM popsal skutečně důkladně a se vším všudy, bych potřeboval několik desítek stránek. Tak dlouhý seriál zase psát nechci. Všimněte si ale, že o technologii COM existují velmi, velmi tlusté knihy: pokud chceme COMu rozumět dopodrobna, nezbude vám než si jednu z nich pořídit a prostudovat.

Protože rozsah tohoto seriálu je omezený (i když to tak místy nevypadá, rozhodl jsem se dát vám jen relativně povrchní a ne úplně podrobný přehled a shrnutí. Potom si ukážeme praktickou ukázku a tím pravděpodobně technologii COM opustíme. Pro zájemce o podrobnější studium nezbude než doporučit některou z výše zmíněných publikací. Fakt je ten, že kdybych se pokusil popsat technologii COM podrobně, tenhle seriál by nikdy neskončil, nikdo by ho však nečetl.

Takže, pojďme na to. COM. O co jde?

COM – jak to vypadá?

Co to vlastně znamená, když se rozhodneme použít při vývoji své aplikace model COM? Technologie COM pracuje na principu klient–server. Základní model fungování je ukázán na následujícím obrázku. COM poskytuje podporu při vytvoření spojení klienta s objektem. Oba zúčastnění pak už dál komunikují přímo, bez dalších zásahů. Komunikace probíhá prostřednictvím mechanismu rozhraní, o kterém jsme se již bavili dříve.

Obrázek, který tady vidíte, se vyznačuje mimořádnou odpudivostí, ale věřím, že mi to nebudete mít za zlé. Pojďme si jej radši popsat: mechanismus COM napomáhá vytvořit spojení mezi klientem a serverem (spodní větev na obrázku), následná komunikace klienta se samotným objektem však už probíhá přímo prostřednictvím rozhraní (horní větev).

Klepněte pro větší obrázek

Co je to COM klient? COM klientem muže být libovolná aplikace, která se připojuje ke COM serveru. Muže jím být také jiná komponenta. Klient žádá o vytvoření objektu a následně s ním pracuje způsobem, který je velmi podobný práci s klasickými objekty v rámci objektově orientovaného programování.

Tolik ke COM klientu. COM server pak poskytuje služby klientské aplikaci. Server je vlastně onou komponentou, a nebo systémem složeným z více komponent. Budeme-li tedy nadále hovořit o komponentách, budeme vlastně mít na mysli COM servery. Existují přitom dva základní druhy COM serverů:

  • tzv. In-process servery, tedy servery, které jsou spuštěny a běží ve stejném procesu jako klientská aplikace. Dá se tady říct, že klient si u sebe „spustí“ svůj vlastní server. Takové komponenty jsou zkompilovány jako DLL knihovny, spouštějí se ve stejném procesu jako klientská aplikace a na požádání vytvářejí objekt či objekty přímo v adresovém prostoru klientské aplikace. Aplikace pak přímo volá metody rozhraní objektu, protože ví, na jaké adrese je rozhraní uloženo.
  • tzv. Out-of-process servery, tedy servery, které jsou spouštěny vně adresového prostoru klientské aplikace. Out-of-process komponenty jsou spustitelné EXE soubory, které dokáží vytvářet COM objekty. Běží ve vlastním adresovém prostoru a s klientskou aplikací jsou spojeny přes zástupné objekty (proxy, stub). V adresovém prostoru klientské aplikace je vytvořen proxy objekt, který nahrazuje chybějící COM objekt. Jinak řečeno, proxy objekt vypadá stejně jako originální objekt, má stejnou sadu rozhraní, ale neumí provádět jeho metody. Jeho úkolem je tvářit se jako požadovaný COM objekt a v případě volání některé z metod tuto metodu zavolat ve skutečné komponentě a předat jí parametry volání. V adresovém prostoru komponenty se nachází jiný proxy objekt, v technologii COM nazývaný stub, který předané parametry převezme. Stub jakýmsi zrcadlovým dvojníkem proxy: sedí v adresovém prostoru komponenty a hraje vlastně COM klienta. Stub zavolá rozhraní COM objektu stejně jako by to udělal klient a obdržené návratové hodnoty odešle zpět proxy objektu v adresovém prostoru klientské aplikace. Proxy objekt je pak předá aplikaci. Podle umístění klienta a serveru lze dále rozlišovat dva druhy Out-of-process serverů – local server (komponenta i klient jsou spuštěny na stejném počítači), a remote server (komponenta a klient sedí na různých počítačích).

Ke komunikace mezi komponentou a klientem se vždy používá mechanismu RPC (Remote Procedure Call). V případě, že komponenta i klient jsou na stejném počítači, je využita jakási odnož RPC nazývaná LRPC (Local Remote Procedure Call).

Základní architektura komponent COM

Typickou architekturu komponenty COM znázorňuje následující obrázek:

Klepněte pro větší obrázek

Komponenta je složena ze své implementace (kterou uživatel typicky nezná a nikdy nepozná) a z jednoho nebo několika rozhraní, které poskytuje svému okolí. Uživatel komponenty dostane k dispozici pouze popis rozhraní a podle tohoto popisu implementuje klienty, kteří budou s komponentou pracovat. Rozhraní se tak stává úplným základem technologie COM.

Teď si možná říkáte, že tohle všechno je moc krásné, ale že jsem vám ještě ani neprozradil, jak se fyzicky komponenty implementují. Nuže, možností je víc, ale COM komponenty jsou velmi často implementovány uvnitř knihovny DLL. Chcete-li někomu dát nebo prodat komponentu, přinesete mu prostě soubor DLL.

Dynamicky linkované knihovny (DLL) vždy poskytují (a zveřejňují) množinu exportovaných funkcí, tedy funkcí, které mohou uživatelé knihovny používat. I v případě, že tuto množinu rozhraní neznáme, ji můžeme zjistit např. použitím příslušného nástroje (např. aplikace dumpbin.exe). Vztah DLL a jejích exportovaných funkcí je podobný vztahu komponenty a jejích rozhraní.

Komponenta poskytuje několik rozhraní, každé rozhraní se skládá z několika funkcí, které může klient volat.

V technologii COM je rozhraní definováno jako specifická paměťová struktura obsahující pole ukazatelů na funkce. Každý ukazatel obsahuje adresu funkce implementované komponentou. Jinak řečeno: implementace všech funkcí jsou ukryty v komponentě, rozhraní pouze obsahují ukazatele na tyto funkce. Zavolá-li klient funkci daného rozhraní, předá se toto volání do komponenty a provede se příslušná funkce. Tomuto mechanismu nemusíte v tomto okamžiku rozumět dopodrobna, stačí tušit, že rozhraní je vlastně jakási tabulka, která obsahuje názvy funkcí a potom pouze ukazuje na samotná těla funkcí, která jsou implementována kdesi v komponentě. O tom, kde jsou tato těla implementována, rozhraní ví, proto na ně může ukazovat. Klient se to však nikdy nemusí dozvědět, ten si povídá pouze s rozhraním.

COM aplikace můžeme implementovat takřka v libovolném programovacím jazyce, nejčastěji používaným je však zřejmě C++. Zmíním tedy teď jen něco málo o C++ a jeho souvislosti s modelem COM, neboť se jedná o základní spojení. Delphi bude následovat mnohem podrobněji, nebojte :-)

V programovacím jazyce C++ se rozhraní implementují jako abstraktní třídy. Abstraktní třída je obecně třída obsahující alespoň jednu virtuální metodu, přičemž může obsahovat datové atributy. V kontextu COM je však za rozhraní považována jen taková abstraktní třída, která obsahuje pouze virtuální metody a neobsahuje žádné atributy (čistá abstraktní třída).

Programový systém napsaný nad technologií COM tedy lze popsat takto: systém je množina komponent, komponenta je množina rozhraní, rozhraní je množina funkcí.

Každé implementované rozhraní vzniká v C++ odděděním ze třídy IUnknown, což je základní třída pro definici rozhraní (deklarovaná v souboru Unknwn.h, obsahuje základní abstraktní metody AddRef(), Release(), QueryInterface()).

Každé rozhraní musí implementovat minimálně tři metody:

  • metoda AddRef() – slouží k počítání referencí na komponentu. V těle AddRef() musíme zvýšit čítač odkazů na komponentu.
  • metoda Release() – slouží k počítání referencí na komponentu. V těle Release() musíme snížit čítač odkazů na komponentu.
  • metoda QueryInterface() – slouží k zjištění, zda komponenta poskytuje požadované rozhraní. Pokud ano, vrátí ukazatel na toto rozhraní.

Při vytvoření nového odkazu na komponentu je nutné zavolat AddRef() – za to bývá zodpovědná sama komponenta; při zrušení odkazu na komponentu je nutné zavolat Release() – měl by provádět klient.

Klient obecně o komponentě nic neví. Potřebuje-li zjistit, zda je k dispozici nějaké rozhraní, zavolá metodu QueryInterface() a předá ji IID tohoto rozhraní (viz níže). K provedení tohoto dotazu se v podstatě používá také rozhraní: IUnknown.

Jinak řečeno: klient má pouze dvě informace:

  • komponenta určitě poskytuje rozhraní IUnknown (neboť toto rozhraní poskytuje každá komponenta)
  • rozhraní IUnknown určitě poskytuje metodu QueryInterface() pro ověření existence zadaného rozhraní (neboť tuto metodu poskytuje každé rozhraní)

Při vytvoření komponenty dostane klient ukazatel na toto rozhraní. Z uvedených informací tedy lze dovodit způsob, jakým klient komunikuje s komponentou:

  • Klient vytvoří komponentu a dostane ukazatel na IUnknow, označme jej pIUnknown.
  • Klient by rád použil rozhraní IIX. Zavolá proto metodu pIUnknown->QueryInterface(IID_IIX).
  • Pokud komponenta poskytuje rozhraní IIX (označované identifikátorem IID_IIX), vrátí klientovi ukazatel na toto rozhraní, označme jej např. pIIX.
  • Klient následně volá metody rozhraní pIIX, např pIIX->metoda()
  • Jakmile klient již rozhraní IIX nechce dále využívat, zavolá pIIX->Release().

Klient přistupuje ke komponentě výhradně přes ukazatele na jednotlivá rozhraní. Protože všechna rozhraní vznikla děděním z IUnknown, mohou být všechna rozhraní manipulována stejně přes ukazatel typovaný na IUnknown.

Závěrem

Tolik pro dnešek k modelu COM. Je mi jasné, že některé uvedené informace mohou začátečníkům připadat trochu nesrozumitelné, ale podle mého názoru by měly být uvedeny. Později se začneme zabývat „čistým Delphi“, což bude znamenat značné zjednodušení života, jak už to tak v Delphi chodí. I tak jsem si však říkal, že stojí za to zmínit obecný COM a jeho původní principy: Delphi nám práci s COMem maximálně zjednoduší a byla by škoda, kdybyste se naučili COM používat, ale přitom mu vůbec nerozuměli.

Témata článku: Software, Programování, .com, Proxy, Release

1 komentář

Nejnovější komentáře

  • gully, gully 19. 10. 2005 0:05:38
    http://umime-to-s-delphi.wz.cz
reklama
Určitě si přečtěte

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

** V Brně byl velký výpadek služeb UPC ** Důvodem je překopnutý páteřní kabel ** V některých lokalitách služby stále nefungují

5.  12.  2016 | Jakub Čížek | 104

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

** Zmizí klasické vyhledávače ** Budeme programovat buňky ** Kvantové počítače překonají šifry

6.  12.  2016 | Jakub Čížek | 36

11 tipů na dobrý stolní počítač: od základu po herní mašiny

11 tipů na dobrý stolní počítač: od základu po herní mašiny

** Postavte si stolní počítač! Máme pro vás 11 vzorových sestav s rozpisem komponent ** Většina tipů cílí na hráče, věnujeme se ale i základnímu PC a počítačům na střih videa ** Nadělte si nový počítač třeba pod stromeček

5.  12.  2016 | Adam Kahánek | 74

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

** V notebooku s cenou nad 20 tisíc nesmí chybět kvalitní displej a rychlé úložiště ** Za dalších deset tisíc můžete dostat navíc styl nebo výkonnější komponenty ** Vybírat můžete z různých velikostí i konstrukcí

8.  12.  2016 | Stanislav Janů | 86


reklama