Umíme to s Delphi, 26. díl - Programovat DLL knihovny může úplně každý - úvod

Zeptáte-li se profesionálního programátora, co jsou to dynamicky linkované knihovny (DLL), pohrdlivě se usměje a začne vám vykládat, že k pochopení jejich principu byste se s ním museli na týden zavřít do jeho tmavého kutlochu a podrobit se intenzivnímu kurzu naplněnému dřinou, askezí a odříkáním. Pravděpodobně se takového scénáře zaleknete. Přitom řešení této zdánlivě bezvýchodné situace je prosté - začíst se do dnešního dílu našeho seriálu.
Připomenutí architektury aplikace

Než se vrhneme na popis knihoven DLL, ve zkratce si připomeneme, z čeho se vlastně „skládá“ aplikace, nepoužíváme-li tyto knihovny. Asi víte (při programování v Delphi je to přinejmenším výhodné:-)), že aplikace vytvořená v Delphi se skládá především z programových jednotek (modulů, units). V těchto modulech jsou uloženy zdrojové kódy procedur a funkcí, a dále nejrůznější datové definice. Každá aplikace (přinejmenším každá, kterou jsme vytvářeli v rámci tohoto seriálu:-)) používá jednak množinu předdefinovaných jednotek (tzv. standardní jednotky), a kromě nich naše vlastní (uživatelské) moduly, standardně pro každý formulář jednu uživatelskou jednotku. Jakmile cítíme, že tvorba (návrh) aplikace je jaksi ve finální fázi, provedeme tzv. kompilaci a překladač (ve spolupráci s linkerem) z těchto jednotek „zkonstruuje“ výsledný *.EXE soubor.

Pojďme se podívat na několik evidentních nevýhod tohoto zaběhnutého postupu:

  • obsah všech jednotek je stále a neoddělitelně součástí *.EXE souboru, čímž roste jeho velikost,
  • součástí *.EXE souboru jsou všechny podprogramy a deklarace obsažené v jednotkách, bez ohledu na to, jestli je aplikace skutečně využívá nebo nikoliv,
  • potřebujeme-li provést určitou změnu funkčnosti aplikace, neobejdeme se bez rekompilace.

Z uvedených nevýhod vyplývají i další, např. procedury, jež jsou součástí modulů, se po spuštění aplikace „povalují“ v operační paměti a nemáme žádné (elementární) možnosti, jak tomu zabránit. Nelze zkrátka v modulu stanovit, že „tato procedura se má načíst do paměti až při určité volbě v hlavním menu).

Co jsou DLL knihovny

Zkratka DLL znamená „Dynamic Link Library“ neboli „dynamicky linkovaná knihovna“. V tomto pojmu je prakticky obsažena celá podstata problému. Knihovna DLL je soubor (experti odpustí zjednodušení), který se k aplikaci linkuje (tedy připojuje) až za běhu.

Pojďme si vše vysvětlit podrobněji. Na první pohled (skutečně jen na ten první) je knihovna DLL podobná programovému modulu. Obsahuje totiž také programový kód (procedury a funkce) a data. Navíc může obsahovat také zdroje Windows, tzv. resources. DLL knihovny jsou samostatnými aplikacemi (spustitelnými), které mají svou vnitřní strukturou relativně blízko k *.EXE souborům.

Pokud bychom měli uvést zásadní charakteristické znaky knihoven DLL, byly by to asi následující dva:

  • knihovny DLL (a jejich obsah, tj. programový kód a data) se k aplikaci připojují (linkují) dynamicky, tj. za jejího běhu, a to až v okamžiku, kdy je to potřeba,
  • knihovny DLL se mohou sdílet, tedy více aplikací používá obsah téže DLL knihovny.

Z těchto důvodů se DLL knihovny používají poměrně hojně, jsou vlastně jedním ze základních prvků samotných Windows (máte-li teď na tváři ironický posměšek, uvědomte si, že princip a podstata DLL knihoven je kvalitní a problémy se stabilitou vznikají někde jinde, viz dále). Kromě Windows používá knihovny DLL nekonečná řada dalších aplikací a konec konců například i Delphi.

Pojďme si uvést několik výhod DLL knihoven:

  • chceme-li provést změnu ve funkčnosti aplikace, není nutné aktualizovat a kompilovat celý program, stačí nahradit jednu verzi knihovny novou,
  • jednotlivé procedury a funkce obsažené v DLL knihovně je možné načítat do paměti až v okamžiku, kdy je to zapotřebí,
  • pokud proceduru nebo funkci z DLL knihovny již nepotřebujeme, je možné ji z paměti uvolnit a neblokovat tak systémové zdroje,
  • DLL knihovny nejsou závislé na programovacím jazyku, takže v aplikaci vytvořené v Delphi je možné bez (velkých) problémů používat knihovnu naprogramovanou třeba v Microsoft Visual C++.
Sdílení jedné knihovny více aplikacemi například znamená, že aktualizace všech aplikací je možná pouhým nahrazením příslušné knihovny. Nezanedbatelnou výhodou je také zmenšení velikosti *.EXE souborů všech aplikací používajících (tutéž) knihovnu.

Nevýhody DLL knihoven

Pokud jste na základě předchozích odstavců dospěli k názoru, že DLL knihovna je něco božsky dokonalého, možná vás zklamu, ale není to úplně pravda. Svět není černobílý, a proto např.
  • DLL knihovny vytvářejí nepředstavitelný chaos ve Windows. Pokud často instalujete a zase odebíráte nové aplikace, po mnohých z nich zůstává v adresáři SYSTEM jedna nebo více knihoven. Tyto knihovny, ač mohou být z principu sdílené, už nikdy nikdo sdílet nebude, ale protože se to nikdo neodváží říci s naprostou jistotou, zůstanou na disku navždy. Tedy - do nejbližšího formátování. Jaký myslíte, že je jednen z důvodů neustálého „kynutí“ adresáře s instalovanými Windows?
  • občas naopak potřebná knihovna chybí (pak se objeví dialog s chybovým hlášením a aplikace se nespustí), což je problém řešitelný jen dvěma způsoby: knihovnu sehnat nebo aplikaci smazat.
  • některé programy fungují jen s určitou verzí knihovny. Řešení stejné jako v předchozím případě.
  • přístup k procedurám a funkcím z knihoven je z pochopitelných důvodů trochu pomalejší.

DLL knihovny teoreticky - pro pokročilé

V několika následujících odstavcích popíši zásadní rozdíl mezi používáním (sdílením) DLL knihoven v šestnáctibitových Windows a dnes, tedy ve Windows32. Tento popis bude koncipována tak, aby byl pochopitelný i naprostým začátečníkům (a navíc jsem přesvědčen, že problematika je to nesmírně zajímavá), nicméně pokud netoužíte do DLL knihoven proniknout nikterak hlouběji a stačí vám základní informace související s jejich vytvářením a používáním, tuto podkapitolu s klidným srdcem přeskočte.

Způsob realizace sdílení DLL knihoven v šestnáctibitových Windows a ve dvaatřicetibitových Windows je radikálně odlišný. Nejprve si popíšeme, jakým způsobem fungovalo sdílení knihoven dříve, tedy ve Win16.

Ve Win16 bylo sdílení realizováno tak, že v operační paměti počítače byla vždy jen jedna instance knihovny (jeden jediný výskyt, knihovna zkrátka byla v paměti jen jednou). Tato instance byla globálně přístupná všem aplikacím a byla tedy připravena ke sdílení. 16bitová knihovna sice využívala zásobník své „mateřské“ aplikace (tedy aplikace, která ji zavedla do paměti), nicméně měla svůj vlastní paměťový prostor. Knihovna byla zavedena do paměti pouze jednou. Při dalších pokusech o její zavedení (např. dalšími aplikacemi, které chtěly používat její funkce) se pouze zvýšila hodnota jakéhosi čítače, který byl součástí Windows. Windows tedy při každé žádosti o zavedení knihovny pouze inkrementovaly svůj čítač a naopak, žádala-li nějaká aplikace o uvolnění knihovny z paměti, čítač se dekrementoval. Byla-li hodnota čítače rovna 0, knihovna se z paměti skutečně uvolnila.

Tato konstrukce samozřejmě programátorům umožňovala mnoho dalších „triků“, např. mohli prostřednictvím sdílené DLL knihovny realizovat komunikaci mezi aplikacemi. Protože jsme si řekli, že každá DLL knihovna měla v paměti svoji část (tzv. segment), bylo možné využívat např. globální proměnné deklarované v knihovně k meziaplikační komunikaci.

Shrňme tedy způsob sdílení knihovny ve Win16 (aplikace A1 a A2 sdílejí knihovnu K1):

Požadavek Provede se
Zaveď aplikaci A1 do paměti Provede se zavedení
Zaveď aplikaci A2 do paměti Provede se zavedení
Aplikace A1 žádá funkci z knihovny K1 Zavede se K1 do paměti a inkrementuje se čítač pro K1, hodnota čítače = 1
Aplikace A2 žádá funkci z knihovny K1 Inkrementuje se čítač pro K1, hodnota čítače = 2
Aplikace A2 chce sdělit aplikaci A1, že výsledek výpočtu je 150 Uloží se hodnota 150 do globální proměnné Mezivysledek, která je deklarována v knihovně K1
Aplikace A1 chce zjistit výsledek operace prováděné aplikací A2 Přečte se hodnota proměnné Mezivysledek, která je deklarována v knihovně K1
Uvolni aplikaci A2 z paměti Aplikace se uvolní, dekrementuje se čítač pro K1, hodnota čítače = 1
Uvolni aplikaci A1 z paměti Aplikace se uvolní, dekrementuje se čítač pro K1, hodnota čítače je rovna nule, takže se uvolní také knihovna K1 z paměti

Tato jednoduchá tabulka demonstruje, jakým způsobem probíhalo sdílení knihoven a komunikace mezi aplikacemi ve Win16.

Ve Win32 je situace radikálně odlišná. Už neplatí jednoduchá pravda, že knihovna je v paměti zavedena nejvýše jedenkrát. Složitější je totiž i vlastní zavádění aplikací do operační paměti. Toto zavádění je však již poněkud vyšší matematikou, proto jej krátce zmíňuji jen v poznámce pro pokročilé uživatele.

Pro naše účely momentálně postačí, řekneme-li si, že každý proces (každá běžící aplikace) ve Windows má k dispozici část (virtuálního) adresního prostoru - můžete si to představit např. tak, že každá spuštěná aplikace má oplocenou určitou část operační paměti počítače a v ní může libovolně řádit. (Prosím, nechytejte mě nyní za slovo - jsem si vědom toho, že tento popis je nepřesný a že např. Windows 95 spravují paměť úplně jinak než Windows NT, ale pro naše účely nemá smysl zabíhat do přílišných podrobností). Jakmile se aplikace namapuje do tohoto adresního prostoru, zjistí se, jaké dynamicky linkované knihovny hodlá tato aplikace využivat a ty se následně namapují do stejného adresního prostoru jako je tato aplikace. Přestože také ve dvaatřicetibitových Windows je možné knihovny sdílet, každá aplikace mapuje knihovnu do svého vlastního adresního prostoru. Čítač, o kterém jsme se zmiňovali při popisování situace ve Win16, je také přítomen, nyní ovšem čítá pokusy o zavedení knihovny pouze v rámci jedné, příslušné aplikace.

Poznámka pro pokročilejší z pokročilých uživatelů:-))

V okamžiku, kdy Windows dostanou žádost o zavedení aplikace do operační paměti, vytvoří se tzv. objekt procesu jádra (zpravidla nazývaný jen proces). Tento proces dostane k dispozici určitý (virtuální) paměťový prostor. Poté se dále vytvoří tzv. objekt mapování souboru jádra. Tento druhý zmiňovaný objekt zabezpečí mapování spustitelného souboru do adresového prostoru procesu. Aplikace se tedy mapuje ze svého umístění na disku.

DLL knihovny - opět pro začátečníky

Vsuvku pro pokročilé uživatele máme za sebou, doufám, že začátečníci nejsou příliš znudění. Nyní se totiž budeme věnovat opět pouze a výhradně jim: povíme si, jak takovou knihovnu DLL v Delphi prakticky naprogramovat a jak ji pak používat. Náš postup rozdělíme do čtyř kroků:
  • Nejprve v Delphi vytvoříme (prázdnou) DLL knihovnu. To ještě v dnešním díle seriálu.
  • Příští týden do ní naprogramujeme dvě funkce: funkci pro výpočet faktoriálu ze zadaného čísla a funkci vracející aktuální rok.
  • Poté vytvoříme jednoduchou aplikaci, která použije uvedené dvě funkce.
  • Na závěr se pokusíme vydat novou verzi aplikace, která bude kromě aktuálního roku vypisovat také informaci o tom, je-li tento rok přestupný.

1. Vytvoření prázdné DLL knihovny

Postup vytvoření knihovny je velmi jednoduchý. V hlavním menu Delphi zvolte File - New..., na kartě New vyberte položku DLL a potvrďte. Otevře se programový kód knihovny:

library Project2;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library`s USES clause AND your project`s (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Classes;

{$R *.RES}

begin
end.

Vidíte, že vlastní programový kód není příliš dlouhý, podstatnou část délky zabírá komentář. Jeho obsahem je (stručně řečeno) upozornění, že pokud vytvořená knihovna hodlá obsahovat procedury nebo funkce, které budou vracet (v některém z parametrů nebo jako svůj výsledek) řetězec, musí být na prvním místě v sekci USES knihovny (i souboru projektu) uvedena jednotka ShareMem. Totéž platí i v případě, že některý z podprogramů knihovny bude řetězec vyžadovat jako vstupní parametr. ShareMem je jednotka s rozhraním ke knihovně BORLNDMM.DLL a tuto knihovnu musíte šířit společně s vytvářenou knihovnou.

Všimněte si, že v úvodu zdrojového kódu není ani klíčové slovo Program ani klíčové slovo Unit, nýbrž klíčové slovo Library (anglicky knihovna). Podle toho poznáte, oč jde. Jinak je ovšem práce se zdrojovým kódem knihovny velmi podobná práci s „obyčejným“ modulem: mezi klíčová slova begin a end by se zapisují případné inicializační příkazy (tedy příkazy, které se mají provést při „spuštění“ knihovny, tedy při jejím zavedení). Před tuto sekci se zapisují všechny podprogramy.

Za týden pokračujeme

V příštím díle seriálu dokončíme dnes nakousnuté téma – knihovny DLL. Budeme se zabývat již ryze praktickými dovednostmi a především dokončíme zbývající kroky příkladu, který jsme právě započali. Vytvoříme v knihovně dvě funkce, naprogramujeme aplikaci, která je používá a následně funkčnost této aplikace modifikujeme změnou ve zdrojovém kódu knihovny.
Diskuze (10) Další článek: Notebook na odpis

Témata článku: Windows, Software, Programování, Jednoduché sdílení, Určitý objekt, DEL, Podobný objekt, Jednoduchý princip, Pokročilá funkce, Paměťový prostor, Znudění, Unity, DLL, Díl, Klíčová funkce, Dynamic-link library, Shorts, Unit, Možný problém, Určitý vir, Pass, Klíčový parametr, Instalovaný windows, Předchozí odstavec, Nekonečná řada, Software na Heureka.cz



Lék proti depresi za stokorunu snižuje riziko těžkého průběhu i úmrtí na onemocnění covid-19

Lék proti depresi za stokorunu snižuje riziko těžkého průběhu i úmrtí na onemocnění covid-19

** Klinická studie zkoumala vliv antidepresiva fluvoxamin na covid-19 ** Počet úmrtí souvisejících s covidem-19 klesl zhruba o 90 % ** Potřeba intenzivní lékařské péče se snížila zhruba o 65 %

Karel Kilián
COVID-19LékyDepreseMedicína
Nejvíc sexy holky ve filmech: 60 nejslavnějších erotických symbolů

Nejvíc sexy holky ve filmech: 60 nejslavnějších erotických symbolů

Krásné ženy jsou pro mnohé erotické a sex symboly. Vybrali jsme ty nejslavnější z několika desetiletí filmové a seriálové tvorby. Najdete zde nejen fotografie, ale také název díla, které herečku proslavilo.

Marek Čech
Filmy a seriály
Rusko obviňuje astronautku NASA ze sabotáže Mezinárodní vesmírné stanice
Jiří Černý
Mezinárodní vesmírná staniceNASARusko
Nad 3,5mm jackem se smráká. Sluchátkový konektor příští rok nejspíš zmizí i z levných telefonů

Nad 3,5mm jackem se smráká. Sluchátkový konektor příští rok nejspíš zmizí i z levných telefonů

** Před pár lety byl 3,5mm konektor nepsaným základem každého telefonu ** Od premiéry iPhonu 7 to však jde s jackem strmě z kopce ** U drahých telefonů chybí úplně a začíná mizet i z modelů střední třídy

Martin Chroust
Střední třída3,5mm jack
Ostření v digitální fotografii – fázové, kontrastní a hybridní, které je lepší?

Ostření v digitální fotografii – fázové, kontrastní a hybridní, které je lepší?

Povedená fotografie by měla mít nejen svoji specifickou atmosféru a povedenou kompozici, ale zejména by měla být ostrá.

Petr Březina
Fotoškola
Tohle nejsou Jedenáctky, ale Linux. Windowsfx 11 opisuje opravdu důkladně
Lukáš Václavík
Windows 11Operační systémyLinux
Recenze Windows 11. Microsoft nás opíjí rohlíkem a omezuje použitelnost

Recenze Windows 11. Microsoft nás opíjí rohlíkem a omezuje použitelnost

** Oproti Desítkám významně stouply hardwarové požadavky ** Windows 11 mají nový vzhled, ale výrazně narušují workflow. ** Potěší vyhledávání, multitasking i rychlejší aktualizace

Petr Urban
Windows 11Testy