Návod: Vytvoření a použití vlastní dynamické knihovny (C++)
Tento podrobný návod ukazuje, jak pomocí integrovaného vývojového prostředí sady Visual Studio vytvořit vlastní dynamickou knihovnu (DLL) napsanou v jazyce Microsoft C++ (MSVC). Pak ukazuje, jak použít knihovnu DLL z jiné aplikace jazyka C++. Knihovny DLL (označované také jako sdílené knihovny v operačních systémech založených na systém UNIX) jsou jedním z nejužitečnějších druhů komponent systému Windows. Můžete je použít jako způsob sdílení kódu a prostředků a zmenšení velikosti aplikací. Knihovny DLL můžou dokonce usnadnit službu a rozšířit aplikace.
V tomto názorném postupu vytvoříte knihovnu DLL, která implementuje některé matematické funkce. Pak vytvoříte konzolovou aplikaci, která používá funkce z knihovny DLL. Seznámíte se také s některými programovacími technikami a konvencemi používanými v knihovnách DLL systému Windows.
Tento názorný postup popisuje tyto úlohy:
Vytvořte projekt knihovny DLL v sadě Visual Studio.
Přidejte do knihovny DLL exportované funkce a proměnné.
Vytvořte projekt konzolové aplikace v sadě Visual Studio.
Použijte funkce a proměnné importované z knihovny DLL v konzolové aplikaci.
Spusťte dokončenou aplikaci.
Podobně jako staticky propojená knihovna exportuje knihovna DLL proměnné, funkce a prostředky podle názvu. Klientská aplikace naimportuje názvy tak, aby používaly tyto proměnné, funkce a prostředky. Na rozdíl od staticky propojené knihovny systém Windows připojí importy v aplikaci k exportům v knihovně DLL v době načtení nebo v době běhu místo jejich připojení v době propojení. Systém Windows vyžaduje další informace, které nejsou součástí standardního modelu kompilace C++, aby tato připojení byla. Kompilátor MSVC implementuje některá rozšíření specifická pro Microsoft do jazyka C++, aby poskytl tyto dodatečné informace. Tato rozšíření vám vysvětlíme, jak budeme pokračovat.
Tento názorný postup vytvoří dvě řešení sady Visual Studio; ten, který sestaví knihovnu DLL, a druhou, která sestaví klientskou aplikaci. Knihovna DLL používá konvenci volání jazyka C. Lze ji volat z aplikací napsaných v jiných programovacích jazycích, pokud se konvence volání a propojení konvencí shodují. Klientská aplikace používá implicitní propojení, kdy Windows aplikaci při načítání propojí s knihovnou DLL. Toto propojení umožňuje aplikaci volat funkce dodané knihovnou DLL stejně jako funkce v staticky propojené knihovně.
Tento názorný postup se nezabývá některými běžnými situacemi. Kód nezobrazuje použití knihoven DLL jazyka C++ jinými programovacími jazyky. Nezobrazuje, jak vytvořit knihovnu DLL jen pro prostředky nebo jak použít explicitní propojení pro načítání knihoven DLL za běhu, nikoli za běhu. Ujišťujte se, že ke všem těmto věcem můžete použít MSVC a Visual Studio.
I když je kód knihovny DLL napsaný v jazyce C++, použili jsme pro exportované funkce rozhraní ve stylu jazyka C. Existují dva hlavní důvody: Zaprvé, mnoho dalších jazyků podporuje import funkcí ve stylu jazyka C. Klientská aplikace nemusí být napsaná v jazyce C++. Za druhé, zabraňuje některým běžným nástrahám souvisejícím s exportovanými třídami a členskými funkcemi. Při exportu tříd je snadné snadno diagnostikovat chyby, protože vše, na co se odkazuje v deklaraci třídy, musí mít také exportované instance. Toto omezení platí pro knihovny DLL, ale ne statické knihovny. Pokud jsou vaše třídy ve stylu prostých starých dat, neměli byste narazit na tento problém.
Odkazy na další informace o knihovnách DLL naleznete v tématu Vytváření knihoven DLL C/C++ v sadě Visual Studio. Další informace o implicitním propojení a explicitním propojení naleznete v tématu Určení, kterou metodu propojení použít. Informace o vytváření knihoven DLL jazyka C++ pro použití s programovacími jazyky, které používají konvence propojení jazyka C, naleznete v tématu Export funkcí jazyka C++ pro použití ve spustitelných souborech jazyka C. Informace o vytváření knihoven DLL pro použití s jazyky .NET naleznete v tématu Volání funkcí knihovny DLL z aplikací jazyka Visual Basic.
Požadavky
- Počítač se systémem Microsoft Windows 7 nebo novějšími verzemi. Pro co nejlepší vývojové prostředí doporučujeme nejnovější verzi Windows.
Kopie sady Visual Studio. Informace o tom, jak stáhnout a nainstalovat Visual Studio, naleznete v tématu Instalace sady Visual Studio. Při spuštění instalačního programu se ujistěte, že je zaškrtnuto vývoj desktopových aplikací s úlohou C++ . Nedělejte si starosti, pokud jste tuto úlohu nenainstalovali při instalaci sady Visual Studio. Instalační program můžete spustit znovu a nainstalovat ho.
- Kopie sady Visual Studio. Informace o tom, jak stáhnout a nainstalovat Visual Studio 2015, najdete v tématu Instalace sady Visual Studio 2015. K instalaci kompilátoru a nástrojů C++ použijte vlastní instalaci, protože nejsou ve výchozím nastavení nainstalované.
Znalost základů používání integrovaného vývojového prostředí sady Visual Studio Pokud jste už dřív používali desktopové aplikace pro Windows, pravděpodobně budete mít přehled. Úvod najdete v tématu Prohlídka funkcí integrovaného vývojového prostředí sady Visual Studio.
Pochopení dostatečného množství základů jazyka C++, abyste mohli pokračovat. Nemějte obavy, neděláme nic moc složitého.
Poznámka
Tento názorný postup předpokládá, že používáte Visual Studio 2017 verze 15.9 nebo novější. Některé starší verze sady Visual Studio 2017 měly chyby v šablonách kódu nebo používaly různé dialogy uživatelského rozhraní. Pokud se chcete vyhnout problémům, použijte Instalační program pro Visual Studio k aktualizaci sady Visual Studio 2017 na verzi 15.9 nebo novější.
Vytvoření projektu knihovny DLL
V této sadě úkolů vytvoříte projekt pro knihovnu DLL, přidáte kód a sestavíte ho. Začněte tím, že spustíte integrované vývojové prostředí sady Visual Studio a pokud potřebujete, přihlaste se. Pokyny se mírně liší podle toho, jakou verzi sady Visual Studio používáte. Ujistěte se, že máte v ovládacím prvku v levém horním rohu této stránky vybranou správnou verzi.
Vytvoření projektu knihovny DLL v sadě Visual Studio 2019
Na řádku nabídek zvolte Soubor>nový>projekt a otevřete dialogové okno Vytvořit nový projekt.
V horní části dialogového okna nastavte jazyk na C++, nastavte platformu pro Windows a nastavte typ projektu na knihovnu.
V seznamu filtrovaných typů projektů vyberte dynamickou knihovnu (DLL) a pak zvolte Další.
Na stránce Konfigurovat nový projekt zadejte do pole Název projektu mathLibrary a zadejte název projektu. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zrušte zaškrtnutí políčka Umístit řešení a projekt do stejného adresáře , pokud je zaškrtnuté.
Zvolte tlačítko Vytvořit a vytvořte projekt.
Po vytvoření řešení se v sadě Visual Studio zobrazí vygenerovaný projekt a zdrojové soubory v okně Průzkumník řešení.
Vytvoření projektu knihovny DLL v sadě Visual Studio 2017
Na řádku nabídek zvolte Soubor>nový>projekt a otevřete dialogové okno Nový projekt.
V levém podokně dialogového okna Nový projekt vyberte Nainstalovaná>plocha Visual C++>Windows. V prostředním podokně vyberte dynamickou knihovnu (DLL). Do pole Název zadejte MathLibrary a zadejte název projektu. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zkontrolujte , jestli není zaškrtnuto políčko Vytvořit adresář pro řešení .
Výběrem tlačítka OK vytvořte projekt.
Po vytvoření řešení se v sadě Visual Studio zobrazí vygenerovaný projekt a zdrojové soubory v okně Průzkumník řešení.
Vytvoření projektu knihovny DLL v sadě Visual Studio 2015 a starších verzích
Na řádku nabídek zvolte Soubor>nový>projekt.
V levém podokně dialogového okna Nový projekt rozbalte nainstalované>šablony a vyberte Visual C++ a pak v prostředním podokně vyberte Konzolová aplikace Win32. Do textového pole Název zadejte MathLibrary a zadejte název projektu. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zkontrolujte , jestli není zaškrtnuto políčko Vytvořit adresář pro řešení .
Kliknutím na tlačítko OK zavřete dialogové okno Nový projekt a spustíte Průvodce aplikací Win32.
Zvolte tlačítko Další. Na stránce Nastavení aplikace vyberte v části Typ aplikace knihovnu DLL.
Výběrem tlačítka Dokončit vytvořte projekt.
Po dokončení řešení uvidíte vygenerovaný projekt a zdrojové soubory v okně Průzkumník řešení v sadě Visual Studio.
V tuto chvíli tato knihovna DLL nedělá moc. Dále vytvoříte soubor hlaviček, který deklaruje funkce, které exportujete knihovnou DLL, a pak do knihovny DLL přidáte definice funkcí, aby byla užitečnější.
Přidání hlavičkového souboru do knihovny DLL
Pokud chcete vytvořit soubor záhlaví pro funkce, zvolte na řádku nabídek možnost Přidat novou položku projektu>.
V dialogovém okně Přidat novou položku v levém podokně vyberte Visual C++. V prostředním podokně vyberte Soubor záhlaví (.h). Jako název souboru záhlaví zadejte MathLibrary.h .
Zvolte tlačítko Přidat a vygenerujte prázdný soubor záhlaví, který se zobrazí v novém okně editoru.
Obsah souboru záhlaví nahraďte tímto kódem:
// MathLibrary.h - Contains declarations of math functions #pragma once #ifdef MATHLIBRARY_EXPORTS #define MATHLIBRARY_API __declspec(dllexport) #else #define MATHLIBRARY_API __declspec(dllimport) #endif // The Fibonacci recurrence relation describes a sequence F // where F(n) is { n = 0, a // { n = 1, b // { n > 1, F(n-2) + F(n-1) // for some initial integral values a and b. // If the sequence is initialized F(0) = 1, F(1) = 1, // then this relation produces the well-known Fibonacci // sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... // Initialize a Fibonacci relation sequence // such that F(0) = a, F(1) = b. // This function must be called before any other function. extern "C" MATHLIBRARY_API void fibonacci_init( const unsigned long long a, const unsigned long long b); // Produce the next value in the sequence. // Returns true on success and updates current value and index; // false on overflow, leaves current value and index unchanged. extern "C" MATHLIBRARY_API bool fibonacci_next(); // Get the current value in the sequence. extern "C" MATHLIBRARY_API unsigned long long fibonacci_current(); // Get the position of the current value in the sequence. extern "C" MATHLIBRARY_API unsigned fibonacci_index();
Tento soubor hlaviček deklaruje některé funkce, které vytvoří generalizovanou fibonacciho sekvenci se dvěma počátečními hodnotami. Volání, které fibonacci_init(1, 1)
vygeneruje známou fibonacciho číselnou sekvenci.
Všimněte si příkazů preprocesoru v horní části souboru. Nová šablona projektu pro projekt knihovny DLL přidá <PROJECTNAME>_EXPORTS
do definovaných maker preprocesoru. V tomto příkladu sada Visual Studio definuje MATHLIBRARY_EXPORTS
, kdy je vytvořen projekt knihovny DLL pro MathLibrary.
MATHLIBRARY_EXPORTS
Když je makro definováno, MATHLIBRARY_API
makro nastaví __declspec(dllexport)
modifikátor u deklarací funkce. Tento modifikátor říká kompilátoru a linkeru, aby exportoval funkci nebo proměnnou z knihovny DLL pro použití jinými aplikacemi. Pokud MATHLIBRARY_EXPORTS
je například nedefinovaný, když je soubor hlavičky zahrnutý klientskou aplikací, MATHLIBRARY_API
použije __declspec(dllimport)
modifikátor na deklarace. Tento modifikátor optimalizuje import funkce nebo proměnné v aplikaci. Další informace naleznete v tématu dllexport, dllimport.
Přidání implementace do knihovny DLL
V Průzkumník řešení klikněte pravým tlačítkem myši na uzel Zdrojové soubory a zvolte Přidat>novou položku. Vytvořte nový soubor .cpp s názvem MathLibrary.cpp stejným způsobem, jakým jste v předchozím kroku přidali nový soubor hlaviček.
V okně editoru vyberte kartu mathLibrary.cpp, pokud je již otevřená. Pokud ne, v Průzkumník řešení poklikejte na MathLibrary.cpp ve složce Zdrojové soubory projektu MathLibrary a otevřete jej.
V editoru nahraďte obsah souboru MathLibrary.cpp následujícím kódem:
// MathLibrary.cpp : Defines the exported functions for the DLL. #include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier #include <utility> #include <limits.h> #include "MathLibrary.h" // DLL internal state variables: static unsigned long long previous_; // Previous value, if any static unsigned long long current_; // Current sequence value static unsigned index_; // Current seq. position // Initialize a Fibonacci relation sequence // such that F(0) = a, F(1) = b. // This function must be called before any other function. void fibonacci_init( const unsigned long long a, const unsigned long long b) { index_ = 0; current_ = a; previous_ = b; // see special case when initialized } // Produce the next value in the sequence. // Returns true on success, false on overflow. bool fibonacci_next() { // check to see if we'd overflow result or position if ((ULLONG_MAX - previous_ < current_) || (UINT_MAX == index_)) { return false; } // Special case when index == 0, just return b value if (index_ > 0) { // otherwise, calculate next sequence value previous_ += current_; } std::swap(current_, previous_); ++index_; return true; } // Get the current value in the sequence. unsigned long long fibonacci_current() { return current_; } // Get the current index position in the sequence. unsigned fibonacci_index() { return index_; }
V okně editoru vyberte kartu mathLibrary.cpp, pokud je již otevřená. Pokud ne, v Průzkumník řešení poklikejte na MathLibrary.cpp ve složce Zdrojové soubory projektu MathLibrary a otevřete jej.
V editoru nahraďte obsah souboru MathLibrary.cpp následujícím kódem:
// MathLibrary.cpp : Defines the exported functions for the DLL. #include "stdafx.h" // use pch.h in Visual Studio 2019 and later #include <utility> #include <limits.h> #include "MathLibrary.h" // DLL internal state variables: static unsigned long long previous_; // Previous value, if any static unsigned long long current_; // Current sequence value static unsigned index_; // Current seq. position // Initialize a Fibonacci relation sequence // such that F(0) = a, F(1) = b. // This function must be called before any other function. void fibonacci_init( const unsigned long long a, const unsigned long long b) { index_ = 0; current_ = a; previous_ = b; // see special case when initialized } // Produce the next value in the sequence. // Returns true on success, false on overflow. bool fibonacci_next() { // check to see if we'd overflow result or position if ((ULLONG_MAX - previous_ < current_) || (UINT_MAX == index_)) { return false; } // Special case when index == 0, just return b value if (index_ > 0) { // otherwise, calculate next sequence value previous_ += current_; } std::swap(current_, previous_); ++index_; return true; } // Get the current value in the sequence. unsigned long long fibonacci_current() { return current_; } // Get the current index position in the sequence. unsigned fibonacci_index() { return index_; }
Pokud chcete ověřit, že všechno zatím funguje, zkompilujte dynamickou knihovnu odkazů. Chcete-li sestavení zkompilovat, zvolte na řádku nabídek možnost Sestavit>řešení. Knihovna DLL a související výstup kompilátoru jsou umístěny do složky s názvem Debug přímo pod složkou řešení. Pokud vytvoříte sestavení vydané verze, výstup se umístí do složky s názvem Release. Výstup by měl vypadat přibližně takto:
1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>pch.cpp
1>dllmain.cpp
1>MathLibrary.cpp
1>Generating Code...
1> Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>stdafx.cpp
1>dllmain.cpp
1>MathLibrary.cpp
1>Generating Code...
1> Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>MathLibrary.cpp
1>dllmain.cpp
1>Generating Code...
1> Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.pdb (Partial PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Blahopřejeme, vytvořili jste knihovnu DLL pomocí sady Visual Studio! Dále vytvoříte klientskou aplikaci, která používá funkce exportované knihovnou DLL.
Vytvoření klientské aplikace, která používá knihovnu DLL
Když vytváříte knihovnu DLL, zamyslete se nad tím, jak ji můžou klientské aplikace používat. Aby bylo možné volat funkce nebo přistupovat k datům exportovaným knihovnou DLL, musí zdrojový kód klienta obsahovat deklarace dostupné v době kompilace. V době propojení linker vyžaduje informace k vyřešení volání funkce nebo přístupu k datům. Knihovna DLL poskytuje tyto informace v knihovně importu, což je soubor, který obsahuje informace o tom, jak najít funkce a data místo skutečného kódu. A v době běhu musí být knihovna DLL k dispozici klientovi v umístění, které může operační systém najít.
Ať už je to vaše vlastní, nebo od jiného výrobce, projekt klientské aplikace potřebuje k použití knihovny DLL několik informací. Potřebuje najít hlavičky, které deklarují export knihovny DLL, knihovny importu pro linker a samotnou knihovnu DLL. Jedním z řešení je zkopírování všech těchto souborů do klientského projektu. U knihoven DLL třetích stran, které se pravděpodobně nezmění, když je váš klient ve vývoji, může být tato metoda nejlepším způsobem, jak je použít. Při sestavování knihovny DLL je ale lepší se vyhnout duplicitám. Pokud vytvoříte místní kopii souborů DLL, které jsou ve vývoji, můžete omylem změnit hlavičkový soubor v jedné kopii, ale ne v druhé nebo použít zastaralé knihovny.
Pokud se chcete vyhnout nesynchronizačnímu kódu, doporučujeme nastavit cestu zahrnutí do projektu klienta tak, aby zahrnovala soubory hlaviček knihovny DLL přímo z projektu knihovny DLL. Také nastavte cestu knihovny v klientském projektu tak, aby zahrnoval knihovny importu knihovny DLL z projektu knihovny DLL. Nakonec zkopírujte sestavenou knihovnu DLL z projektu knihovny DLL do výstupního adresáře sestavení klienta. Tento krok umožňuje klientské aplikaci používat stejný kód knihovny DLL, který sestavíte.
Vytvoření klientské aplikace v sadě Visual Studio
Na řádku nabídek zvolte Soubor>nový>projekt a otevřete dialogové okno Vytvořit nový projekt.
V horní části dialogového okna nastavte jazyk na C++, nastavte platformu pro Windows a nastavte typ projektu na konzolu.
V filtrovaném seznamu typů projektů zvolte Konzolová aplikace a pak zvolte Další.
Na stránce Konfigurovat nový projekt zadejte do pole Název projektu MathClient a zadejte název projektu. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zrušte zaškrtnutí políčka Umístit řešení a projekt do stejného adresáře , pokud je zaškrtnuté.
Zvolte tlačítko Vytvořit a vytvořte projekt klienta.
Pro vás je vytvořen minimální projekt konzolové aplikace. Název hlavního zdrojového souboru je stejný jako název projektu, který jste zadali dříve. V tomto příkladu se jmenuje MathClient.cpp. Můžete ji sestavit, ale zatím nepoužívá knihovnu DLL.
Vytvoření klientské aplikace v sadě Visual Studio 2017
Chcete-li vytvořit aplikaci jazyka C++, která používá knihovnu DLL, kterou jste vytvořili, zvolte na řádku nabídek možnost Soubor>nový>projekt.
V levém podokně dialogového okna Nový projekt vyberte v části Nainstalovaná>aplikace Visual C++ možnost Plocha systému Windows. V prostředním podokně vyberte konzolovou aplikaci systému Windows. Do textového pole Název zadejte název projektu MathClient. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zkontrolujte , jestli není zaškrtnuto políčko Vytvořit adresář pro řešení .
Zvolte OK a vytvořte projekt klientské aplikace.
Pro vás je vytvořen minimální projekt konzolové aplikace. Název hlavního zdrojového souboru je stejný jako název projektu, který jste zadali dříve. V tomto příkladu se jmenuje MathClient.cpp. Můžete ji sestavit, ale zatím nepoužívá knihovnu DLL.
Vytvoření klientské aplikace v sadě Visual Studio 2015
Chcete-li vytvořit aplikaci jazyka C++, která používá knihovnu DLL, kterou jste vytvořili, zvolte na řádku nabídek možnost Soubor>nový>projekt.
V levém podokně dialogového okna Nový projekt vyberte Win32 v části Nainstalované>šablony>Visual C++. V prostředním podokně vyberte konzolovou aplikaci Win32. Do textového pole Název zadejte název projektu MathClient. Ponechte výchozí hodnoty názvu umístění a řešení. Nastavte řešení tak, aby se vytvořilo nové řešení. Zkontrolujte , jestli není zaškrtnuto políčko Vytvořit adresář pro řešení .
Kliknutím na tlačítko OK zavřete dialogové okno Nový projekt a spustíte Průvodce aplikací Win32. Na stránce Přehled v dialogovém okně Průvodce aplikací Win32 zvolte tlačítko Další.
Na stránce Nastavení aplikace v části Typ aplikace vyberte Konzolová aplikace, pokud ještě není vybraná.
Výběrem tlačítka Dokončit vytvořte projekt.
Po dokončení průvodce se pro vás vytvoří minimální projekt konzolové aplikace. Název hlavního zdrojového souboru je stejný jako název projektu, který jste zadali dříve. V tomto příkladu se jmenuje MathClient.cpp. Můžete ji sestavit, ale zatím nepoužívá knihovnu DLL.
Pokud chcete volat funkce MathLibrary ve zdrojovém kódu, musí projekt obsahovat soubor MathLibrary.h . Tento soubor hlaviček můžete zkopírovat do projektu klientské aplikace a pak ho přidat do projektu jako existující položku. Tato metoda může být dobrou volbou pro knihovny třetích stran. Pokud ale pracujete na kódu knihovny DLL a klienta najednou, můžou se soubory hlaviček dostat mimo synchronizaci. Chcete-li se tomuto problému vyhnout, nastavte v projektu cestu Další adresáře zahrnutí tak, aby zahrnovala cestu k původní hlavičce.
Přidání hlavičky knihovny DLL do cesty zahrnutí
Kliknutím pravým tlačítkem myši na uzel MathClient v Průzkumník řešení otevřete dialogové okno Stránky vlastností.
V rozevíracím seznamu Konfigurace vyberte Všechny konfigurace , pokud ještě není vybraná.
V levém podokně vyberte Vlastnosti>konfigurace C/C++>Obecné.
V podokně vlastností vyberte rozevírací seznam vedle textového pole Další adresáře zahrnutí a pak zvolte Upravit.
Poklikejte v horním podokně dialogového okna Další zahrnutí adresářů a povolte tak ovládací prvek pro úpravy. Nebo zvolte ikonu složky a vytvořte novou položku.
V ovládacím prvku pro úpravy zadejte cestu k umístění souboru záhlaví MathLibrary.h . Můžete zvolit ovládací prvek se třemi tečkou (...) a přejít do správné složky.
Můžete také zadat relativní cestu ze zdrojových souborů klienta do složky, která obsahuje soubory hlaviček knihovny DLL. Pokud jste postupovali podle pokynů pro umístění projektu klienta do samostatného řešení od knihovny DLL, měla by relativní cesta vypadat takto:
..\..\MathLibrary\MathLibrary
Pokud jsou vaše projekty dll a klientů ve stejném řešení, relativní cesta může vypadat takto:
..\MathLibrary
Pokud jsou knihovny DLL a klientské projekty v jiných složkách, upravte relativní cestu tak, aby odpovídala. Nebo pomocí ovládacího prvku se třemi tečky vyhledejte složku.
Po zadání cesty k souboru záhlaví v dialogovém okně Další adresáře zahrnout zvolte tlačítko OK . V dialogovém okně Stránky vlastností zvolte tlačítko OK a uložte provedené změny.
Teď můžete zahrnout soubor MathLibrary.h a použít funkce, které deklaruje v klientské aplikaci. Obsah souboru MathClient.cpp nahraďte tímto kódem:
// MathClient.cpp : Client app for MathLibrary DLL.
// #include "pch.h" Uncomment for Visual Studio 2017 and earlier
#include <iostream>
#include "MathLibrary.h"
int main()
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
std::cout << fibonacci_index() << ": "
<< fibonacci_current() << std::endl;
} while (fibonacci_next());
// Report count of values written before overflow.
std::cout << fibonacci_index() + 1 <<
" Fibonacci sequence values fit in an " <<
"unsigned 64-bit integer." << std::endl;
}
Tento kód lze zkompilovat, ale ne propojit. Pokud teď sestavíte klientskou aplikaci, zobrazí se v seznamu chyb několik LNK2019 chyb. Je to proto, že v projektu chybí některé informace: Zatím jste nezadali, že projekt má závislost na knihovně MathLibrary.lib . A neřekli jste linkerovi, jak najít soubor MathLibrary.lib .
Pokud chcete tento problém vyřešit, můžete soubor knihovny zkopírovat přímo do projektu klientské aplikace. Linker najde a použije ho automaticky. Pokud se ale knihovna i klientská aplikace vyvíjí, může to vést ke změnám v jedné kopii, která se nezobrazuje v druhé. Chcete-li se tomuto problému vyhnout, můžete nastavit vlastnost Další závislosti tak, aby systém sestavení, že váš projekt závisí na MathLibrary.lib. A můžete nastavit cestu k adresářům další knihovny v projektu tak, aby zahrnovala cestu k původní knihovně při propojení.
Přidání knihovny dll importu do projektu
Klikněte pravým tlačítkem na uzel MathClient v Průzkumník řešení a zvolte Vlastnosti a otevřete dialogové okno Stránky vlastností.
V rozevíracím seznamu Konfigurace vyberte Všechny konfigurace , pokud ještě není vybraná. Zajišťuje, že všechny změny vlastností platí pro sestavení Debug i Release.
V levém podokně vyberte Vstup linkeru>Vlastnosti>konfigurace. V podokně vlastností vyberte rozevírací ovládací prvek vedle textového pole Další závislosti a pak zvolte Upravit.
V dialogovém okně Další závislosti přidejte mathLibrary.lib do seznamu v horním ovládacím prvku pro úpravy.
Kliknutím na tlačítko OK se vrátíte do dialogového okna Stránky vlastností.
V levém podokně vyberte Obecné propojení>vlastností>konfigurace. V podokně vlastností vyberte rozevírací ovládací prvek vedle textového pole Další adresáře knihovny a pak zvolte Upravit.
Poklikáním v horním podokně dialogového okna Další adresáře knihovny povolíte ovládací prvek pro úpravy. V ovládacím prvku pro úpravy zadejte cestu k umístění souboru MathLibrary.lib . Ve výchozím nastavení je ve složce s názvem Ladit přímo ve složce řešení KNIHOVNY DLL. Pokud vytvoříte sestavení vydané verze, soubor se umístí do složky s názvem Release. Makro můžete použít
$(IntDir)
, aby linker mohl najít knihovnu DLL bez ohledu na to, jaký druh sestavení vytvoříte. Pokud jste postupovali podle pokynů k umístění projektu klienta do samostatného řešení od projektu knihovny DLL, relativní cesta by měla vypadat takto:..\..\MathLibrary\$(IntDir)
Pokud jsou vaše knihovny DLL a klientské projekty v jiných umístěních, upravte relativní cestu tak, aby odpovídala.
Po zadání cesty k souboru knihovny v dialogovém okně Další adresáře knihovny zvolte tlačítko OK a vraťte se do dialogového okna Stránky vlastností. Chcete-li uložit změny vlastnosti, zvolte OK .
Klientská aplikace se teď může úspěšně zkompilovat a propojit, ale pořád nemá všechno, co potřebuje ke spuštění. Když operační systém načte vaši aplikaci, vyhledá knihovnu DLL pro MathLibrary. Pokud knihovna DLL nemůže najít v určitých systémových adresářích, v cestě prostředí nebo v adresáři místní aplikace, zatížení se nezdaří. V závislosti na operačním systému se zobrazí chybová zpráva podobná této:
Jedním ze způsobů, jak se vyhnout tomuto problému, je zkopírovat knihovnu DLL do adresáře, který obsahuje spustitelný soubor klienta jako součást procesu sestavení. Do projektu můžete přidat událost po sestavení a přidat příkaz, který zkopíruje knihovnu DLL do výstupního adresáře sestavení. Zadaný příkaz zkopíruje knihovnu DLL pouze v případě, že chybí nebo se změnila. Na základě konfigurace sestavení používá makra ke kopírování do a z umístění ladění nebo vydané verze.
Kopírování knihovny DLL v události po sestavení
Klikněte pravým tlačítkem na uzel MathClient v Průzkumník řešení a zvolte Vlastnosti a otevřete dialogové okno Stránky vlastností.
V rozevíracím seznamu Konfigurace vyberte Všechny konfigurace , pokud ještě není vybraná.
V levém podokně vyberte Události sestavení vlastností>>konfigurace po sestavení událostí.
V podokně vlastností vyberte ovládací prvek pro úpravy v poli Příkazového řádku . Pokud jste postupovali podle pokynů pro umístění projektu klienta do samostatného řešení od projektu knihovny DLL, zadejte tento příkaz:
xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"
Pokud jsou vaše knihovny DLL a klientské projekty v jiných adresářích, změňte relativní cestu ke knihovně DLL tak, aby odpovídala.
Kliknutím na tlačítko OK uložte změny vlastností projektu.
Teď má vaše klientská aplikace všechno, co potřebuje k sestavení a spuštění. Sestavte aplikaci tak, že na řádku nabídek zvolíte Sestavit řešení sestavení>. Okno Výstup v sadě Visual Studio by mělo mít v závislosti na vaší verzi sady Visual Studio něco jako v následujícím příkladu:
1>------ Build started: Project: MathClient, Configuration: Debug Win32 ------
1>MathClient.cpp
1>MathClient.vcxproj -> C:\Users\username\Source\Repos\MathClient\Debug\MathClient.exe
1>1 File(s) copied
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Blahopřejeme, vytvořili jste aplikaci, která volá funkce v knihovně DLL. Teď spusťte aplikaci, abyste viděli, co dělá. Na řádku nabídek zvolte Spustit ladění>bez ladění. Visual Studio otevře příkazové okno pro spuštění programu. Poslední část výstupu by měla vypadat takto:
Stisknutím libovolné klávesy zavřete příkazové okno.
Teď, když jste vytvořili knihovnu DLL a klientskou aplikaci, můžete experimentovat. Zkuste nastavit zarážky v kódu klientské aplikace a spusťte aplikaci v ladicím programu. Podívejte se, co se stane, když přejdete do volání knihovny. Přidejte do knihovny další funkce nebo napište jinou klientskou aplikaci, která používá vaši knihovnu DLL.
Když nasadíte aplikaci, musíte také nasadit knihovny DLL, které používá. Nejjednodušší způsob, jak vytvořit knihovny DLL, nebo které zahrnete od třetích stran, je zpřístupnit je do stejného adresáře jako vaše aplikace. Označuje se jako místní nasazení aplikace. Další informace o nasazení naleznete v tématu Nasazení v jazyce Visual C++.