Příklady vytváření komplexu v delphi dll. Vytvoření dll knihovny v Delphi. Praxe a příklady

Chcete-li vytvořit novou knihovnu DLL v Delphi, vyberte příkaz nabídky Soubor > Nový > Jiné. V panelu Kategorie položek okno Nové předměty vybrat uzel Projekty Delphi a poté dvakrát klikněte na prvek Knihovna dynamických odkazů v pravém panelu okna.

Mistr Průvodce DLL vytvoří hlavní soubor zdrojového kódu DLL, který vypadá téměř stejně jako zdrojový kód generovaný pro normální aplikaci. Jediný rozdíl je. že tento soubor začíná vyhrazeným slovem knihovna, ale ne program.

projekt knihovny1; (Důležitá poznámka o správě paměti DLL: ShareMem musí být první jednotkou v klauzuli USES vaší knihovny A v klauzuli vašeho projektu (vyberte Project-View Source) Klauzule USES, pokud vaše knihovna DLL exportuje jakékoli procedury nebo funkce, které předávají řetězce jako parametry nebo funkci výsledky.To platí pro všechny řetězce předávané do a z vaší DLL – dokonce i ty, které jsou vnořeny do záznamů a tříd.ShareMem je jednotka rozhraní pro správce sdílené paměti BORLNDMM.DLL, který musí být nasazen spolu s vaší knihovnou DLL. pomocí BORLNDMM.DLL předejte informace o řetězcích pomocí parametrů PChar nebo ShortString. ) (Projekt -> Zobrazit zdroj)), pokud vaše knihovna DLL exportuje jakékoli procedury nebo funkce, které předávají řetězce jako parametry nebo výsledky provádění funkcí. To platí pro všechny řetězce předané nebo přijaté z vaší DLL, a dokonce i ty vnořené v záznamech a třídách. Modul ShareMem je modul rozhraní pro správce sdílené paměti BORLNDMM.DLL, který musíte nasadit s vaší knihovnou DLL. Chcete-li se vyhnout použití BORLNDMM.DLL, předejte informace o řetězci pomocí parametrů PChar nebo ShortString. ) používá SysUtils, Classes; ($R *.res) začátek konec.

Vše, co nyní musíte udělat, je přidat podprogram před blok začátek-konec, to je vše. Získáte tak interní rutinu, kterou lze použít v DLL, ale ne v externích aplikacích. Pokud chcete rutinu volat z jiných aplikací a jiných knihoven DLL, bude nutné ji exportovat. Chcete-li exportovat rutinu podle názvu, přidejte ji do seznamu exportů. Seznam exportů má stejnou syntaxi jako seznam používá, kromě toho, co je v seznamu exportů jakýkoli prvek je podprogram, nikoli modul.

Seznam exportů obvykle umístěn bezprostředně před blokem začátek-konec. Podívejte se na výpis 1, který ukazuje zdrojový kód jednoduché knihovny FirstLib.dll, který exportuje jednu funkci.

Výpis 1. Jednoduchá knihovna DLL

LibraryFirstLib; funkce Max3(Num1, Num2, Num3: Integer): Integer; stdcall; begin Vysledek:= Num1; if Num2 > Result then Result:= Num2; if Num3 > Result then Result:= Num3; konec; ( Export funkce Max3 ) exportuje Max3; začátek konec.

Když přidáte podprogram do seznamu exportů, tím exportujete rutinu podle jejího názvu. Pomocí direktivy můžete také exportovat podprogram pod jiným názvem název nebo pořadovou hodnotou pomocí směrnice index. Použijte však směrnici index Nedoporučeno.

Následuje příklad exportu direktivy s řadovou hodnotou nebo s jiným názvem:

Exportuje název Max3 "MyMax3Function", SaySomething index 1;

Statické načítání je nejjednodušší ze dvou možných způsobů načtení knihovny DLL. Statické načítání se také nazývá dynamické propojení při spouštění ( dynamické propojení při načítání), protože použité knihovny DLL se automaticky načtou během spouštění aplikace.

Chcete-li staticky načíst knihovnu DLL, musíte zkopírovat deklaraci podprogramu a volající aplikaci a označit ji direktivou externí, který říká kompilátoru, že podprogram je buď v objektovém souboru, nebo v DLL.

Když importujete podprogramy z DLL, musíte je označit direktivou externí, za kterým následuje název knihovny DLL, která obsahuje implementaci podprogramu. Následuje příklad importu funkce MaxZ z knihovny FirstLib.dll:

Funkce Max3(číslo1, číslo2, číslo3: celé číslo): celé číslo; stdcall; externí "FirstLib.dll";

Pokud chcete, můžete podprogram během importu dokonce přejmenovat. Chcete-li to provést, musíte podprogram deklarovat pod jiným názvem a na konci deklarace zadat původní název pomocí direktivy název:

Funkce Max(Num1, Num2, Num3: Integer): Integer; stdcall; externí název "FirstLib.dll" "Max3";

Funkci můžete také importovat z knihovny DLL. Chcete-li to provést, musíte vytvořit modul importu a do sekce napsat standardní záhlaví podprogramu rozhraní, a její vnější realizace - v odd implementace tento modul. Výpis 2 zobrazuje úplný kód pro modul importu knihovny. FirstLib.dll.

Výpis 2. Import knihovny FirstLib.dll.

UnitFirstLibInf; funkce rozhraní Max3(Num1, Num2, Num3: Integer): Integer; stdcall; implementace const FirstLib = "FirstLib.dll"; (Kompilátor je informován, že implementace funkce Max3 je v knihovně FirstLib.dll) function Max3; externalFirstLib; konec.

Po vytvoření knihovny DLL a jejího importéru otestujte knihovnu DLL, abyste se ujistili. že podprogram funguje správně. Protože nemůžete spustit samotnou knihovnu DLL, musíte vytvořit testovací aplikaci, která bude přistupovat ke knihovně DLL. Nejrychlejší způsob, jak toho dosáhnout, je vytvořit projektový tým přidáním nového projektu k aktuálnímu projektu. Chcete-li to provést, musíte kliknout pravým tlačítkem myši na prvek Projektová skupina1 v okně projektový manažer(Project Manager) a vyberte příkaz z kontextové nabídky Přidat nový projekt, jak je znázorněno na Obr. jeden.

Výpis 3. Testování rutiny Max3 importované z FirstLib.dll.

Jednotka Jednotka1; rozhraní používá Windows, zprávy, SysUtils, varianty, třídy, grafiku, ovládací prvky, formuláře, dialogy, FirstLibInf, StdCtrls; zadejte TMainForm = class(TForm) Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Label1: T Label; Label2: T Label; Label3: T Label; Max3Button: TButton; procedure Max3ButtonClick(Sender: TObject); private ( Private deklarace ) public ( Public deklarace ) end; var MainForm: TMainForm; implementace ($R *.dfm) procedure TMainForm.Max3ButtonClick(Sender: TObject); var LargestNumber: Integer; begin NejvětšíNumber:= Max3(StrToInt(Upravit1.Text), StrToInt(Upravit2.Text), StrToInt(Upravit3.Text)); MessageDlg(Format("Největší číslo: %d.", ), mtInformation, , 0); konec; konec.

Reference: The Inner World of Borland Delphi 2006. Ivan Chladni.

Práce s DLL

DLL - Dynamic Link Library jinak dynamicky propojovaná knihovna, která umožňuje opakované použití stejných funkcí v různých programech. Je to vlastně docela šikovný nástroj, zvláště když jednou napsanou knihovnu lze použít v mnoha programech. V dnešní lekci se naučíme pracovat s dll a samozřejmě jak je vytvářet!

No, začněme!

Začněme vytvořením naší první knihovny dynamických odkazů! Jdeme do Delphi a hned vlezeme do nabídky Soubor -> Nový -> Jiné.

Vyberte ze seznamu Dynamic-Link Library (ve verzích starších než 2009 Delphi se tato položka nazývá DLL Wizard).

Výsledkem je, že máme pouze okno s kódem, všimněte si, že zde nemáme žádný formulář!

Nyní začíná zábava. Pojďme si v knihovně napsat naše první postupy.

knihovna Projekt2; //Pravděpodobně jste si již všimli, že místo programu //při vytváření dll se používá slovo knihovna. // Knihovna signifier. používá SysUtils, Dialogs, Classes; // Pozornost! Nezapomeňte tyto moduly specifikovat, jinak kód nebude fungovat ($R *.res) (TATO ČÁST JE VLOŽTE KÓD DLL) Procedure FirstCall; stdcall; vývozní; //Stdcall - Tento příkaz posune parametry na zásobníku //zprava doleva a zarovná se na standardní hodnotu //Export lze v zásadě vynechat, použít k upřesnění //exportu procedury nebo funkce. Begin ShowMessage("Moje první dll procedura"); //Zprávu na obrazovce nazýváme End; DoubleProcedureCall; stdcall; vývozní; Begin ShowMessage("Moje druhá procedura"); //Zprávu na obrazovce nazýváme End; Exportuje FirstCall, DoubleCall; //Export obsahuje seznam exportovaných položek. //Což bude později importováno nějakým programem. začátek Konec.

Tady se prozatím zastavíme. pro jednoduchý příklad to bude stačit. Nyní uložíme náš projekt, osobně jsem jej uložil pod názvem Project2.dll a stisknutím kombinace kláves CTRL + F9 knihovnu zkompilujeme. Ve složce, kam jste uložili soubor dpr, se musí objevit soubor s příponou dll, to je naše nově vytvořená knihovna. Mám to nazvané Project2.dll

Pojďme se nyní zabývat voláním procedur z této knihovny. Vytvoříme novou aplikaci podle standardního schématu. Před námi není nic neobvyklého, jen forma. Novou aplikaci uložíme do nějaké složky. A do stejné složky zkopírujeme nově vytvořenou knihovnu dll. Tito. v tomto příkladu Project2.dll

Nyní si musíte vybrat, jak volat funkce z knihovny. Existují celkem dva způsoby volání.

Metoda číslo 1

Možná je to nejjednodušší způsob volání procedur v knihovně.

Ideální pro práci pouze s jednou knihovnou.

Tady jsme...

Za klíčové slovo implementace napište následující kód:

Zde, jak jste pravděpodobně uhodli, říkáme programu názvy našich procedur a říkáme, že jsou v dll knihovně, v mém případě s názvem Project2.dll

Nyní, abychom mohli tyto procedury volat, potřebujeme pouze vložit jejich jména kamkoli do kódu, což nyní uděláme. Na formulář z karty Standard hodíme 2 komponenty Button a na každé vytvoříme obsluhu události OnClick

Po kliknutí na první tlačítko:

Po kliknutí na druhé tlačítko:

To je vše!

Metoda číslo 2:

Složitější než první, ale má své výhody a hlavně je ideální pro pluginy.

Chcete-li použít tuto metodu, nejprve deklarujeme několik globálních proměnných:

Poté po klíčovém slovu implementace napíšeme proceduru, která načte naši knihovnu:

Load ProcedureMyLibrary(FileName: String); Začít LibHandle:= LoadLibrary(PWideChar(FileName));//Načtěte knihovnu! // Pozornost! PChar pro verze nižší než 2009 Delphi Pokud LibHandle = 0 then begin MessageBox(0," Nelze načíst knihovnu",0,0); výstup; konec; FirstCall:= GetProcAddress(LibHandle,"FirstCall");//Získat ukazatel na objekt //1. parametr je odkaz na modul knihovny //2. parametr je název objektu v dll DoubleCall:= GetProcAddress(LibHandle,"DoubleCall"); Pokud @FirstCall = nula, pak začněte//Zkontrolujte přítomnost této funkce v knihovně. MessageBox(0,"Nelze načíst knihovnu",0,0); výstup; konec; Pokud @DoubleCall = nula, pak začněte//Zkontrolujte přítomnost této funkce v knihovně. MessageBox(0,"Nelze načíst knihovnu",0,0); výstup; konec; Konec

Poté na formuláři vytvoříme obsluhu události OnCreate, do které pomocí nově vytvořené procedury načteme naši knihovnu

Procedure TForm1.FormCreate(Sender: TObject); Začít LoadMyLibrary("Project2.dll"); konec;

Abychom mohli volat potřebné procedury z naší knihovny, musíme opět vložit jejich jména kamkoli do kódu. K tomu hodíme 2 komponenty Button na formulář ze záložky Standard a na každé vytvoříme obsluhu události OnClick

Po kliknutí na první tlačítko:

Procedure TForm1.Button1Click(Sender: TObject); BeginFirstCall; // Název procedury, která je v dll End;

Po kliknutí na druhé tlačítko:

Procedure TForm1.Button2Click(Sender: TObject); Zahájit DoubleCall; // Název procedury, která je v dll End;

A nakonec na formuláři vytvoříme obslužnou rutinu události OnDestroy, ve které uvolníme dll knihovnu z paměti

To je vše! Druhý způsob se ukázal jako značně těžkopádný, jeho výhoda je však v upřesnění objektu uloženého v knihovně.



Úvod

Vzhledem k rychlému rozvoji programovacích technologií se stále více lidí potýká s problémem zvýšení schopností svých programů. Tento článek je věnován této problematice, konkrétně programování DLL v Borland Delphi. Navíc, protože se dotkneme problematiky používání DLL, dotkneme se i importu funkcí z cizích DLL (včetně systémových, tedy WinAPI).

DLL aplikace

Proč jsou tedy knihovny DLL potřebné a kde se používají?. Zde je jen několik oblastí jejich použití:

Samostatné knihovny Obsahuje další funkce užitečné pro programátory. Například funkce pro práci s řetězci, nebo složité knihovny pro převod obrázků. Úložiště zdrojů DLL může ukládat nejen programy a funkce, ale také všechny druhy zdrojů – ikony, obrázky, pole řetězců, nabídky a tak dále. Podporované knihovny Příklady zahrnují knihovny takových známých balíčků, jako jsou: DirectX, ICQAPI (API pro ICQ), OpenGL atd. Části programu Například DLL může ukládat okna programu (formuláře) a tak dále. Pluginy (Pluginy) Tam je skutečný prostor pro myšlenky programátora! Pluginy jsou doplňky k programu, které rozšiřují jeho možnosti. V tomto článku se například podíváme na teorii tvorby pluginu pro vlastní program. Sdílený prostředek DLL (Dynamic Link Library) může využívat více programů nebo procesů najednou (tzv. sdílení je sdílený prostředek)

Stručný popis funkcí a triků pro práci s DLL

Jaké triky a funkce tedy musíte použít pro práci s DLL? Pojďme analyzovat dvě metody pro import funkcí z knihovny:

1 způsob. Vazba DLL k programu.

Toto je nejjednodušší a nejjednodušší způsob použití funkcí importovaných z knihovny DLL. Tato metoda má však (a měli byste tomu věnovat pozornost) velmi významnou nevýhodu - pokud není nalezena knihovna, kterou program používá, program se jednoduše nespustí, zobrazí chybu a hlásí, že zdroj DLL nebyl nalezen. A knihovna bude prohledána: v aktuálním adresáři, v adresáři programu, v adresáři WINDOWS\SYSTEM atd. Takže pro začátek - obecná forma této techniky:


FunctionName (nebo ProcedureName) název funkce (nebo procedury), která bude použita ve vašem programu; Par1, Par2, ... názvy parametrů funkce nebo procedury; Par1Type, Par2Type, ... typy parametrů funkce nebo procedury (například Integer); ReturnType návratový typ (pouze funkce); direktiva stdcall, která se musí přesně shodovat s direktivou použitou v samotné DLL; externí direktiva "DLLNAME.DLL" specifikující název externí DLL, ze které bude daná funkce nebo procedura importována (v tomto případě DLLNAME.DLL); name "FunctionName" ("ProcedureName") direktiva, která specifikuje přesný název funkce v samotné DLL. Toto je volitelná direktiva, která vám umožňuje používat v programu funkci, která má název odlišný od skutečného (který má v knihovně); index FunctionIndex (ProcedureIndex) Direktiva, která určuje pořadové číslo funkce nebo procedury v knihovně DLL. Toto je také nepovinná směrnice.

Jedná se o mnohem složitější, ale také elegantnější metodu. Postrádá nevýhodu prvního způsobu. Jediná věc, která je nepříjemná, je množství kódu potřebného k implementaci této techniky a problém je v tom, že funkce importovaná z DLL je dostupná pouze tehdy, když je tato DLL načtena a je v paměti ... Můžete si přečíst příklad níže, ale prozatím - krátký popis funkcí WinAPI používaných touto metodou:

LoadLibrary(LibFileName: PChar) Načte zadanou knihovnu LibFileName do paměti. V případě úspěchu funkce vrátí popisovač (THandle) do DLL v paměti. GetProcAddress(Modul: THandle; ProcName: PChar) získá adresu funkce exportované knihovny. V případě úspěchu funkce vrátí popisovač (TFarProc) funkci v načtené knihovně DLL. FreeLibrary(LibModule:THandle) zruší platnost LibModule a uvolní paměť s ním spojenou. Je třeba poznamenat, že po zavolání této procedury již nejsou funkce této knihovny dostupné.

Praxe a příklady

Nyní je čas uvést několik příkladů použití výše uvedených metod a technik:

Příklad 1: Vazba DLL k programu


Nyní to samé, ale druhým způsobem - s dynamickým zatížením:


Poznámka:

Měli byste se zdržet používání typu řetězec ve funkcích knihovny, protože při jeho používání dochází k problémům se „sdílením paměti“. Více si o tom můžete přečíst (i když v angličtině) v textu prázdného projektu DLL, který Delphi vytváří (Soubor -> Nový -> DLL). Je tedy lepší použít PChar a ten pak v případě potřeby převést na řetězec pomocí StrPas.

Nyní pojďme analyzovat samotnou DLL přímo:

Příklad 3. Zdroj projektu MYDLL.DPR


Umístění v DLL zdrojích a formulářích

Do DLL můžete umístit nejen funkce, ale také kurzory, obrázky, ikony, nabídky, textové řádky. U toho se nezastavíme. Uvedu pouze, že pro načtení zdroje je třeba načíst DLL a poté, co obdržíme jeho deskriptor, načíst samotný zdroj s příslušnou funkcí (LoadIcon, LoadCursor atd.). V této části se jen krátce dotkneme umístění oken aplikací (tj. formulářů v Delphi) v knihovnách DLL.

Chcete-li to provést, musíte vytvořit novou knihovnu DLL a přidat do ní nový formulář (Soubor -> Nový -> DLL a poté Soubor -> Nový formulář). Dále, pokud je formulář dialogové okno (modální formulář (bsDialog)), přidejte do knihovny DLL následující funkci (například formulář se nazývá Form1 a jeho třída je TForm1):

Příklad 4 Umístění formuláře do knihovny DLL


Pokud potřebujete umístit nemodální formulář do DLL, musíte provést dvě funkce - otevření a zavření formuláře. V tomto případě musíte vynutit DLL, aby si pamatovala popisovač tohoto formuláře.

Vytváření pluginů

Zde nebudeme podrobně zvažovat pluginy, protože. výše uvedené příklady vám pomohou snadno pochopit lví podíl programování DLL. Jen připomenu, že plug-in je doplněk k programu, který rozšiřuje jeho možnosti. Současně musí samotný program nutně zajistit přítomnost takových doplňků a umožnit jim plnit jejich účel.

To znamená, že například chcete-li vytvořit zásuvný modul pro grafický editor, který by prováděl konverzi obrázků, musíte v zásuvném modulu poskytnout alespoň dvě funkce (a podle toho tyto funkce volat v programu) - funkci to by vrátilo název zásuvného modulu (a/nebo jeho typ) pro přidání tohoto zásuvného modulu do nabídky (nebo panelu nástrojů), plus hlavní funkcí je odeslat a přijmout obrázek. Tito. nejprve program vyhledá pluginy, poté pro každý nalezený zavolá svou identifikační funkci s přesně definovaným názvem (například GetPluginName) a přidá požadovanou položku do nabídky, poté, pokud uživatel tuto položku vybral, zavolá druhá funkce, která předá vstupní obrázek (nebo název souboru, obsahující tento obrázek), a tato funkce zase obrázek zpracuje a vrátí v nové podobě (nebo název souboru s novým obrázkem). V tom je celý smysl pluginu... :-)

Epilog

Tento článek ukazuje hlavní aspekty používání a vytváření knihoven DLL v Borland Delphi. Pokud máte nějaké dotazy - pošlete mi je na e-mail:

Vzhledem k rychlému rozvoji programovacích technologií se stále více lidí potýká s problémem zvýšení schopností svých programů. Tento článek je věnován této problematice, konkrétně programování DLL v Borland Delphi. Navíc, protože se dotkneme problematiky používání DLL, dotkneme se i importu funkcí z cizích DLL (včetně systémových, tedy WinAPI).

DLL aplikace

Proč jsou tedy knihovny DLL potřebné a kde se používají?. Zde je jen několik oblastí jejich použití:
  • Samostatné knihovny, obsahující další funkce užitečné pro programátory. Například funkce pro práci s řetězci, nebo složité knihovny pro převod obrázků.
  • Obchody se zdroji. V DLL můžete ukládat nejen programy a funkce, ale také všechny druhy zdrojů - ikony, obrázky, pole řetězců, nabídky atd.
  • Podpora knihoven. Příkladem jsou knihovny takových známých balíčků, jako jsou: DirectX, ICQAPI(API pro ICQ), OpenGL atd.
  • Části programu. DLL může například ukládat okna programu (formuláře) atd.
  • Pluginy(Pluginy). - Tam je skutečný prostor pro myšlenky programátora! Pluginy jsou doplňky k programu, které rozšiřují jeho možnosti. V tomto článku se například podíváme na teorii tvorby pluginu pro vlastní program.
  • Sdílený zdroj. DLL( Knihovna dynamických odkazů) může být používáno několika programy nebo procesy najednou (tzv. sdílení- sdílený zdroj)

Stručný popis funkcí a triků pro práci s DLL

Jaké triky a funkce tedy musíte použít pro práci s DLL? Pojďme analyzovat dvě metody pro import funkcí z knihovny:

1 způsob. Vazba DLL k programu. Toto je nejjednodušší a nejjednodušší způsob použití funkcí importovaných z knihovny DLL. Tato metoda má však (a měli byste tomu věnovat pozornost) velmi významnou nevýhodu - pokud není nalezena knihovna, kterou program používá, program se jednoduše nespustí, zobrazí chybu a hlásí, že zdroj DLL nebyl nalezen. A knihovna bude prohledána: v aktuálním adresáři, v adresáři programu, v adresáři WINDOWS\SYSTEM atd.
Takže pro začátek - obecná forma této techniky:

implementace
...
funkce NázevFunkce(Par1: Par1Type; Par2: Par2Type; ...): ReturnType; stdcall; externí"DLLNAME.DLL" název"Název funkce" index FuncIndex;
// nebo (pokud to není funkce, ale procedura):
postup ProcedureName(Par1: Par1Type; Par2: Par2Type; ...); stdcall; externí"DLLNAME.DLL" název"název procedury" index ProcIndex;

Tady: Název funkce(nebo Název procedury) - název funkce (nebo procedury), která bude použita ve vašem programu;
Par1, Par2,...- názvy parametrů funkce nebo procedury;
Par1Type, Par2Type, ...- typy parametrů funkce nebo procedury (např. Celé číslo);
návratový typ- typ návratové hodnoty (pouze pro funkci);
stdcall- direktiva, která se musí přesně shodovat s direktivou použitou v samotné DLL;
externí "DLLNAME.DLL"- direktiva určující název externí DLL, ze které bude daná funkce nebo procedura importována (v tomto případě - DLLNAME.DLL);
název "FunctionName" ("ProcedureName")- direktiva, která specifikuje přesný název funkce v samotné DLL. Toto je volitelná direktiva, která vám umožňuje používat v programu funkci, která má název odlišný od skutečného (který má v knihovně);
index FunctionIndex(ProcedureIndex)- direktiva, která určuje pořadové číslo funkce nebo procedury v DLL. Toto je také nepovinná směrnice.

2 způsobem. Dynamické načítání DLL. Jedná se o mnohem složitější, ale také elegantnější metodu. Postrádá nevýhodu prvního způsobu. Jediná věc, která je nepříjemná, je množství kódu potřebného k implementaci této techniky a problém je v tom, že funkce importovaná z DLL je dostupná pouze tehdy, když je tato DLL načtena a je v paměti ... Můžete si přečíst příklad níže, ale prozatím - krátký popis funkcí WinAPI používaných touto metodou:

LoadLibrary(libfilename: PChar) - načtení zadané knihovny LibFileName do paměti. Při úspěchu funkce vrátí handle ( Thandle) DLL v paměti.
GetProcAddress(Modul: Thandle; ProcName: PChar) - přečte adresu exportované knihovní funkce. Při úspěchu funkce vrátí handle ( TFarProc) funkce v načtené DLL.
volná knihovna(LibModul: Thandle) - zruší platnost modulu LibModule a uvolní paměť s ním spojenou. Je třeba poznamenat, že po zavolání této procedury již nejsou funkce této knihovny dostupné.

Praxe a příklady


Nyní je čas uvést několik příkladů použití výše uvedených metod a technik:

Nyní to samé, ale druhým způsobem - s dynamickým zatížením:

(... Zde je záhlaví souboru a definice formuláře TForm1 a jeho instance Form1)

var
Form1: TForm1;
GetSimpleText: funkce(LangRus: Boolean): PChar;
LibHandle: THandle;

ProcedureButton1Click(Sender: TObject);
začít
("Vyčistíme" adresu funkce od "nečistoty")
@GetSimpleText:= nula;
(Pokouším se načíst knihovnu)
LibHandle:= LoadLibrary("MYDLL.DLL");
(Pokud je vše v pořádku)
pokud LibHandle >= 32, pak začněte
(...pak se snažíme získat adresu funkce v knihovně)
@GetSimpleText:= GetProcAddress(LibHandle,"GetSimpleText");
(Pokud je zde vše v pořádku)
if @GetSimpleText<>pak nula
(... pak tuto funkci zavoláme a ukážeme výsledek)
ShowMessage(StrPas(GetSimpleText(True)));
konec;
(A nezapomeňte uvolnit paměť a uvolnit DLL)
FreeLibrary(LibHandle);
konec;

POZNÁMKA : Měli byste se zdržet používání typu řetězec ve funkcích knihovny, protože při jeho používání dochází k problémům se „sdílením paměti“. Více si o tom můžete přečíst (i když v angličtině) v textu prázdného projektu DLL, který Delphi vytváří (Soubor -> Nový -> DLL). Je tedy lepší použít PChar a ten pak v případě potřeby převést na řetězec pomocí StrPas.

Nyní pojďme analyzovat samotnou DLL přímo:

Umístění v DLL zdrojích a formulářích


Do DLL můžete umístit nejen funkce, ale také kurzory, obrázky, ikony, nabídky, textové řádky. U toho se nezastavíme. Uvedu pouze, že pro načtení zdroje je třeba načíst DLL a poté, co obdržíme jeho deskriptor, načíst samotný zdroj s příslušnou funkcí (LoadIcon, LoadCursor atd.). V této části se jen krátce dotkneme umístění oken aplikací (tj. formulářů v Delphi) v knihovnách DLL.

Chcete-li to provést, musíte vytvořit novou knihovnu DLL a přidat do ní nový formulář (Soubor -> Nový -> DLL a poté Soubor -> Nový formulář). Dále, pokud je formulář dialogové okno (modální formulář (bsDialog)), přidejte do knihovny DLL následující funkci (například formulář se nazývá Form1 a jeho třída je TForm1):

Pokud potřebujete umístit nemodální formulář do DLL, musíte provést dvě funkce - otevření a zavření formuláře. V tomto případě musíte vynutit DLL, aby si pamatovala popisovač tohoto formuláře.

Vytváření pluginů

Zde nebudeme podrobně zvažovat pluginy, protože. výše uvedené příklady vám pomohou snadno pochopit lví podíl programování DLL. Jen připomenu, že plug-in je doplněk k programu, který rozšiřuje jeho možnosti. Současně musí samotný program nutně zajistit přítomnost takových doplňků a umožnit jim plnit jejich účel.

To znamená, že například chcete-li vytvořit zásuvný modul pro grafický editor, který by prováděl konverzi obrázků, musíte v zásuvném modulu poskytnout alespoň dvě funkce (a podle toho tyto funkce volat v programu) - funkci to by vrátilo název zásuvného modulu (a/nebo jeho typ) pro přidání tohoto zásuvného modulu do nabídky (nebo panelu nástrojů), plus hlavní funkcí je odeslat a přijmout obrázek. Tito. nejprve program vyhledá pluginy, poté pro každý nalezený zavolá svou identifikační funkci s přesně definovaným názvem (například GetPluginName) a přidá požadovanou položku do nabídky, poté, pokud uživatel tuto položku vybral, zavolá druhá funkce, která předá vstupní obrázek (nebo název souboru, obsahující tento obrázek), a tato funkce zase obrázek zpracuje a vrátí v nové podobě (nebo název souboru s novým obrázkem). V tom je celý smysl pluginu... :-)

DLL umožňuje kombinovat opakovaně použitelný kód do jednoho celku. Funkce z knihoven DLL lze dynamicky propojovat za běhu, na rozdíl od funkcí z balíčků Delphi, které jsou staticky propojeny ve fázi kompilace aplikace.

Chcete-li vytvořit knihovnu DLL, musíte nejprve spustit příkaz nabídky Soubor|Nový|Jiné a vybrat prvek Průvodce DLL na stránce Nová v dialogu Nová položka.

Průvodce DLL automaticky vytvoří prázdnou šablonu pro knihovnu DLL. Na rozdíl od normálního modulu, který začíná klíčovým slovem unit, DLL modul začíná klíčovým slovem knihovny. Sekce použití modulu DLL vyžaduje, aby byly zahrnuty pouze dva balíčky: SysUtils a Classes.

Vytvoření funkce DLL se skládá z několika kroků:

1. Nejprve v implementační části modulu zadejte podpis funkce a naprogramujte kód, který funkce vykonává.

3. Konečně funkce, která má být používána nejen uvnitř modulu, ale také volána z jiných aplikací, by měla být deklarována jako exportovatelná v sekci exportů.

Funkce z DLL lze volat jak z aplikací vyvinutých v Delphi, tak z aplikací napsaných v jiných programovacích jazycích, jako je C++.

Pořadí přidělování paměti pro parametry a její uvolňování se pro různé programovací jazyky liší. Aby se předešlo chybě při běhu, deklarace funkce v knihovně DLL a její deklarace v aplikaci musí používat stejný mechanismus předávání parametrů. Při deklaraci procedury nebo funkce lze zadat jeden z následujících mechanismů předávání parametrů:

Způsob předání parametru je uveden středníkem za popisem funkce. Například:

funkce F1(X, Y, Z: Real]: Real; stdcall;.

Různé metody předávání parametrů určují pořadí, ve kterém jsou parametry předávány (zleva doprava nebo zprava doleva), a také určují, kdo uvolní paměť zásobníku (volaná procedura nebo volající procedura). Při použití knihoven DLL jako komponent volaných z aplikací v jiných programovacích jazycích by měl být použit příslušný modifikátor volání. Pro aplikace C++ se používá modifikátor volání stdcall.

Aby mohla být funkce popsaná v DLL volána z jiné aplikace, musí být funkce exportována. Seznam všech exportovaných funkcí je uveden v sekci exporty oddělené čárkami

a končí středníkem. Funkce lze exportovat třemi způsoby:

Podle názvu funkce použitého v DLL;

Podle názvu funkce, zadaného jako název exportu;

Podle indexu přiřazeného funkci.

Aby bylo možné funkci přiřadit nějaký index, měl by být uveden v sekci exportů za názvem funkce s klíčovým slovem index.

Aby byla exportovaná funkce volána pod jiným názvem, než je název použitý v DLL, musíte v sekci exporty za názvem funkce zadat klíčové slovo name a nový název exportu pro tuto funkci.

DLL - knihovna není spustitelný modul. K získání jeho kódu stačí projekt zkompilovat.

projekt knihovny;

SysUtils, Třídy;

funkce F1(X, Y: Integer): Integer; stdcall;

Statické propojení DLL

DLL lze propojit staticky nebo dynamicky. Když je zahrnuta knihovna DLL, je načtena do paměti aplikace.

U statického odkazu se knihovna DLL načte jednou při spuštění aplikace. V průběhu provádění aplikace odkazuje název funkce importované ze staticky propojené knihovny DLL na stejnou funkci (vstupní bod knihovny DLL) ve stejné knihovně DLL. Všechny funkce z knihovny DLL, které budou v aplikaci zpočátku použity, musí být deklarovány jako externí. V tomto případě byste měli v případě potřeby zadat modifikátor volání. Pokud je funkce volána indexem, pak by jí měl být přidělen název použitý v aplikaci a index funkce v knihovně DLL.

Externí deklarace funkcí se provádějí v sekci implementace před použitím těchto funkcí.

Externí oznámení funkcí s klíčovým slovem external určuje, že bude použito statické propojení.

TForm = class(TForm)

Editl: TEdit; [Pole pro zadání první hodnoty)

Edit2: TEdit; (Pole pro zadání druhé hodnoty)

Edit3: TEdit; (Pole pro zobrazení výsledku

spuštění funkce z DLL)

Tlačítko: TButton; (Volání funkce použité jménem)

Tlačítko2: TButton; [Volání funkce používané indexem)

procedure ButtonlClickfSender: TObject);

procedure Button2Click(Sender: TObject);

(soukromá prohlášení)

(Veřejná prohlášení)

(Deklarace exportovaných funkcí)

funkce Fl (i: celé číslo; j: celé číslo): celé číslo; stdcall;

externí "projectl.dll";

funkce F2 (i: celé číslo; j: celé číslo): celé číslo; stdcall;

externí "Projectl.dll index 2;

procedure TForml.ButtonlClick(Sender: TObject);

(Volání exportované funkce)

Edit3.Text:=IntToStr(Fl(StrToInt(Editl.Text),StrToInt(Edit2.Text)) ));

procedure TForml.Button2Click(Sender: TObject);

Edit3.Text:=JntToStr(F2(StrToInt(Editl.Text),StrToInt(Edit2.Text)));

Dynamické propojení DLL

Na rozdíl od statického odkazu na knihovnu DLL, ke kterému dochází při načtení aplikace, lze dynamický odkaz na knihovnu DLL vytvořit v kterémkoli okamžiku provádění programu. Jakmile byla funkce volána z knihovny DLL, lze ji zakázat. Při současném použití několika knihoven DLL to poskytuje významnou úsporu paměti. Chcete-li dynamicky propojit DLL, použijte funkce Windows API. Windows API - je to sada standardních funkcí používaných k implementaci interakce s operačním systémem.

Při volání funkce z dynamické knihovny DLL byste místo definování názvu funkce jako externího v případě statického propojení měli definovat nový typ, který odpovídá typu volané funkce, a vytvořit proměnnou tohoto typu.

Chcete-li volat funkci z dynamické knihovny DLL, postupujte takto:

1. Vytvořte nový typ. odpovídající typu volané funkce (název nového typu lze zadat za sekci typu).

Například:

TMyFl=function(i,j:Integer):Integer; stdcall;

2. V části var části rozhraní modulu vytvořte proměnnou typu vytvořené funkce. Například: MyFl: TMyFl;

3. Před načtením knihovny DLL deklarujte proměnnou typu Integer, která bude obsahovat deskriptor zahrnuté knihovny.

4. Zavolejte metodu LoadLibrary, která načte knihovnu DLL. Například; h:=LoadLibrary("Projectl.dll");

5. Zkontrolujte, zda bylo připojení knihovny úspěšné. Pokud je název DLL nesprávný nebo knihovna DLL nebyla nalezena, funkce LoadLibrary vrátí 0.

6. V případě úspěšného připojení knihovny DLL byste měli získat adresu funkce. K tomu slouží funkce GetProcAddress Windows API, jejíž parametry jsou deskriptor knihovny DLL a název funkce zásuvného modulu. Například: @MyFl: =GetProcAddress(h, "Fl");

7. Pokud je získána adresa funkce, pak by hodnota adresy (v našem příkladu @MyFl) neměla být rovna nule.

8. V tomto okamžiku můžete volat funkci z dynamicky propojené knihovny DLL.

9. Chcete-li uvolnit a odpovídajícím způsobem uvolnit knihovnu DLL, zavolejte metodu FreeLibrary, která knihovnu DLL odpojí.

Windows, Zprávy, SysUtils, Varianty, Třídy, Grafika,

Ovládací prvky, formuláře, dialogy, StdCtrls;

TForm = class(TForm)

Tlačítko3: TButton;

postup Button3Click

procedure TForml.Button3Click(Sender: TObject);

h:=LoadLibrary("Projectl.dll");

pokud h<>0 pak

@MyFl:=GetProcAddress(h,"Fl");

pokud @MyFl<>pak nula

Edit3.Text:=IntToStr(MyFl(StrToInt(Editl.Text),

StrToInt(Edit2.Text)));

Použití knihovny DLL k vyvolání běžných modálních dialogů.

Výsledkem provádění procedury z knihovny DLL může být zobrazení nějakého modálního dialogu. Chcete-li to provést, vytvořte objekt formuláře v exportované metodě, zobrazte jej jako modální dialogové okno a poté objekt formuláře odstraňte. V tomto případě by měl samotný formulář poskytovat volání metody Close k ukončení dialogu.

Pro vytvoření formuláře se používá metoda Create, jako parametr, kterému se předává ukazatel na nadřazený formulář, formulář volající aplikace. Tento parametr je předán volané funkci DLL.

projekt knihovny;

Unitl_DLL v "Unitl_DLL.pas" (Forml);

procedure MyModalForm (var Z:Integer ;F:TForm1); stdcall;

Form1:=TForml.Create(F);

(Parametr F je předán při volání procedury a obsahuje ukazatel

na nadřazený formulář - formulář vyvolávací aplikace)