Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit stapsgewijze overzicht wordt uitgelegd hoe u de Visual Studio IDE gebruikt om uw eigen DLL-bibliotheek (Dynamic Link Library) te maken die is geschreven in Microsoft C++ (MSVC) en hoe u het DLL-bestand gebruikt vanuit een andere C++-app. DLL's, ook wel gedeelde bibliotheken genoemd in UNIX-besturingssystemen, zijn een van de handigste soorten Windows-onderdelen. U kunt ze gebruiken om code en resources te delen en om de grootte van uw apps te verkleinen. DLL's kunnen het zelfs eenvoudiger maken om uw apps te onderhouden en uit te breiden.
In dit scenario maakt u een DLL waarmee een aantal wiskundige functies worden geïmplementeerd. Vervolgens maakt u een console-app die gebruikmaakt van de functies uit het DLL-bestand. U krijgt ook een inleiding tot enkele programmeertechnieken en conventies die worden gebruikt in Windows-DLL's.
In deze handleiding worden de volgende stappen doorlopen:
- Maak een DLL-project in Visual Studio.
- Voeg geëxporteerde functies en variabelen toe aan het DLL-bestand.
- Maak een console-app-project in Visual Studio.
- Gebruik de functies en variabelen die zijn geïmporteerd uit het DLL-bestand in de console-app.
- Voer de voltooide app uit.
Net als bij een statisch gekoppelde bibliotheek exporteert een DLL-bestand variabelen, functies en resources op naam. Een client-app importeert de namen om deze variabelen, functies en resources te gebruiken. In tegenstelling tot een statisch gekoppelde bibliotheek verbindt Windows de importbewerkingen in uw app met de exports in een DLL tijdens het laden of tijdens runtime, in plaats van ze te verbinden tijdens het koppelen. Windows vereist extra informatie die geen deel uitmaakt van het standaard C++-compilatiemodel om deze verbindingen te maken. De MSVC-compiler implementeert enkele Microsoft-specifieke extensies voor C++ om deze extra informatie te bieden. In de stapsgewijze rondleiding worden deze extensies uitgelegd naarmate u verdergaat.
In dit scenario worden twee Visual Studio-oplossingen gemaakt: een oplossing waarmee het DLL-bestand wordt gebouwd en één waarmee de client-app wordt gebouwd. Het DLL-bestand maakt gebruik van de C-aanroepconventie. Het kan worden aangeroepen vanuit apps die zijn geschreven in andere programmeertalen, zolang het platform, de aanroepende conventies en het koppelen van conventies overeenkomen. De client-app maakt gebruik van impliciete koppeling, waarbij Windows de app koppelt aan het DLL-bestand tijdens het laden. Door deze koppeling kan de app de door dll geleverde functies aanroepen, net zoals de functies in een statisch gekoppelde bibliotheek.
In deze handleiding worden sommige veelvoorkomende situaties niet behandeld. In de code wordt het gebruik van C++-DLL's door andere programmeertalen niet weergegeven. Er wordt niet getoond hoe u een DLL met alleen resources maakt of hoe u expliciete koppelingen gebruikt om DLL's tijdens runtime te laden in plaats van tijdens de laadtijd. Wees gerust, u kunt MSVC en Visual Studio gebruiken om al deze dingen te doen.
Hoewel de code van het DLL-bestand is geschreven in C++, gebruikt u C-stijlinterfaces voor de geëxporteerde functies. Er zijn twee belangrijke redenen voor deze keuze: Ten eerste ondersteunen veel andere talen het importeren van C-functies in C-stijl. De client-app hoeft niet te worden geschreven in C++. Ten tweede worden enkele veelvoorkomende valkuilen met betrekking tot geëxporteerde klassen en lidfuncties vermeden. Het is eenvoudig om fouten te maken die moeilijk te diagnosticeren zijn bij het exporteren van klassen, omdat alles waarnaar in een klassedeclaratie wordt verwezen een geïmporteerde instantie moet hebben. Deze beperking is van toepassing op DLL's, maar niet op statische bibliotheken. Als uw klassen in de stijl van 'plain-old-data' zijn, zou u dit probleem niet tegenkomen.
Zie C/C++ DLL's maken in Visual Studio voor meer informatie over DLL's. Zie Bepalen welke koppelingsmethode moet worden gebruikt voor meer informatie over impliciete koppelingen en expliciete koppelingen. Zie C++- functies exporteren voor gebruik in uitvoerbare bestanden in de C-taal voor informatie over het maken van C++-DLL's voor gebruik met programmeertalen die gebruikmaken van koppelingsconventies in C++. Zie DLL-functies aanroepen vanuit Visual Basic Applications voor informatie over het maken van DLL-bestanden voor gebruik met .NET-talen.
Vereiste voorwaarden
- Windows 7 of hoger. Gebruik de nieuwste versie van Windows voor de beste ontwikkelervaring.
Visual Studio. Zie Visual Studio installeren voor meer informatie over het downloaden en installeren van Visual Studio. Wanneer u het installatieprogramma uitvoert, moet u ervoor zorgen dat de desktopontwikkeling met de C++ -workload is gecontroleerd. Als u deze workload niet hebt geïnstalleerd toen u Visual Studio hebt geïnstalleerd, hoeft u zich geen zorgen te maken. U kunt het installatieprogramma opnieuw uitvoeren en het nu installeren.
- Visual Studio. Zie Visual Studio 2015 installeren voor meer informatie over het downloaden en installeren van Visual Studio 2015. Gebruik een aangepaste installatie om de C++-compiler en hulpprogramma's te installeren, omdat deze niet standaard zijn geïnstalleerd.
Een goed begrip van de basisprincipes van het gebruik van de Visual Studio IDE. Als u eerder Windows desktop-apps hebt gebruikt, kunt u het waarschijnlijk bijhouden. Zie Visual Studio IDE-functierondleiding voor een inleiding.
Enige bekendheid met de C++-taal. Maak je geen zorgen, de stapsgewijze uitleg bevat niets al te ingewikkelds.
Opmerking
In dit scenario wordt ervan uitgegaan dat u Visual Studio 2017 versie 15.9 of hoger gebruikt. Sommige eerdere versies van Visual Studio 2017 hadden defecten in de codesjablonen of gebruikten verschillende dialoogvensters voor de gebruikersinterface. Als u problemen wilt voorkomen, gebruikt u het installatieprogramma van Visual Studio om Visual Studio 2017 bij te werken naar versie 15.9 of hoger.
Het DLL-project maken
In de volgende set taken maakt u een project voor uw DLL, voegt u code toe en bouwt u het. Als u wilt beginnen, start u de Visual Studio IDE en meldt u zich aan als dat nodig is. De instructies variëren enigszins, afhankelijk van de versie van Visual Studio die u gebruikt. Als u de stappen voor de gewenste versie van Visual Studio wilt zien, gebruikt u de versieselector boven aan de inhoudsopgave op deze pagina.
Een DLL-project maken in Visual Studio
Selecteer Bestand>nieuw> op de menubalk Project om het dialoogvenster Een nieuwe Project maken te openen.
Stel bovenaan het dialoogvenster Taal in op C++, stel Platform in op Windows en stel Projecttype in op Bibliotheek.
Selecteer in de gefilterde lijst met projecttypen Dynamic-link Library (DLL) en selecteer vervolgens Volgende.
Als u dat type niet ziet, controleert u of desktopontwikkeling met C++ is geïnstalleerd, zoals beschreven in de vereisten.
Voer op de pagina Uw nieuwe project configurerenMathLibrary in het vak Projectnaam in om een naam voor het project op te geven. Laat de standaardwaarden voor de locatie - en oplossingsnaam staan . Stel oplossing in op Nieuwe oplossing maken. Schakel de optie Oplossing plaatsen en project in dezelfde map uit als deze is ingeschakeld.
Selecteer de knop Maken om het project te maken.
Wanneer de oplossing is gemaakt, ziet u het gegenereerde project en de bronbestanden in het venster Solution Explorer in Visual Studio.
Een DLL-project maken in Visual Studio 2017
Selecteer Bestand>nieuw> op de menubalk Project om het dialoogvenster Nieuw Project te openen.
Selecteer in het linkerdeelvenster van het dialoogvenster Nieuw projectGeïnstalleerd>Visual C++>Windows Desktop. Selecteer Dynamic-Link Bibliotheek (DLL) in het middelste deelvenster. Voer MathLibrary in het vak Naam in om een naam voor het project op te geven. Laat de standaardwaarden voor de locatie - en oplossingsnaam staan . Stel oplossing in op Nieuwe oplossing maken. Selecteer Map maken voor oplossing als het niet is aangevinkt.
Selecteer de knop OK om het project te maken.
Wanneer de oplossing is gemaakt, ziet u het gegenereerde project en de bronbestanden in het venster Solution Explorer in Visual Studio.
Een DLL-project maken in Visual Studio 2015 en oudere versies
Selecteer in de menubalk Bestand>Nieuw>Project.
Vouw Geïnstalleerde> uit in het linkerdeelvenster van het dialoogvenster Nieuwe Project en selecteer Visual C++. Selecteer in het middelste deelvenster Win32-consoletoepassing. Voer MathLibrary in als de naam voor het project. Wijzig de standaardwaarden voor de locatie - en oplossingsnaam niet. Stel oplossing in op Nieuwe oplossing maken. Selecteer Map maken voor oplossing.
Selecteer OK om het dialoogvenster Nieuw project te sluiten en de Wizard voor Win32-toepassingen te starten.
Kies Volgende. Selecteer DLL op de pagina Toepassingsinstellingen onder Toepassingstype.
Selecteer Voltooien om het project te maken.
Wanneer de wizard klaar is met de oplossing, ziet u het gegenereerde project en de bronbestanden in het venster Solution Explorer in Visual Studio.
Op dit moment doet deze DLL niet veel. Vervolgens maakt u een headerbestand om de functies te declareren die uw DLL exporteert en voegt u vervolgens de functiedefinities toe aan het DLL-bestand om het nuttiger te maken.
Een headerbestand toevoegen aan het DLL-bestand
Als u een koptekstbestand voor uw functies wilt maken, selecteert u op de menubalk Project >Nieuw item toevoegen.
Selecteer Visual C++ in het dialoogvenster Nieuw item toevoegen in het linkerdeelvenster. Selecteer in het middelste deelvenster headerbestand (.h). Geef
MathLibrary.hop als de naam voor het headerbestand.
Selecteer de knop Toevoegen om een leeg headerbestand te genereren, dat wordt weergegeven in een nieuw editorvenster.
Vervang de inhoud van het headerbestand door deze code:
// 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();
Dit headerbestand declareert enkele functies voor het produceren van een gegeneraliseerde Fibonacci-reeks, op basis van twee initiële waarden. Een aanroep naar fibonacci_init(1, 1) genereert de bekende Fibonacci-getallenreeks.
Let op de preprocessorinstructies boven aan het bestand. De nieuwe projectsjabloon voor een DLL-project voegt <PROJECTNAME>_EXPORTS toe aan de gedefinieerde preprocessormacro's. In dit voorbeeld definieert Visual Studio MATHLIBRARY_EXPORTS wanneer uw MathLibrary DLL-project wordt gebouwd.
Wanneer de MATHLIBRARY_EXPORTS macro is gedefinieerd, stelt de MATHLIBRARY_API macro de __declspec(dllexport) wijzigingsfunctie in op de functiedeclaraties. Deze wijzigingsfunctie vertelt de compiler en linker om een functie of variabele uit het DLL-bestand te exporteren voor gebruik door andere toepassingen. Wanneer MATHLIBRARY_EXPORTS niet is gedefinieerd, bijvoorbeeld wanneer het headerbestand door een clienttoepassing wordt opgenomen, wordt MATHLIBRARY_API de __declspec(dllimport) modifier toegepast op de declaraties. Deze wijzigingsfunctie optimaliseert het importeren van de functie of variabele in een toepassing. Zie dllexport, dllimport voor meer informatie.
Een implementatie toevoegen aan het DLL-bestand
Klik in Solution Explorer met de rechtermuisknop op het knooppunt Bronbestanden en selecteerNieuw item>. Maak een nieuw
.cppbestand met de naamMathLibrary.cpp, net zoals u in de vorige stap een nieuw headerbestand hebt toegevoegd.Selecteer in het editorvenster het
MathLibrary.cpptabblad als het al is geopend. Als dat niet het probleem is, dubbelklikt u in Solution Explorer opMathLibrary.cppde map Bronbestanden van het project MathLibrary om het te openen.Vervang in de editor de inhoud van het
MathLibrary.cppbestand door de volgende code:// 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_; }
Selecteer in het editorvenster het tabblad voor MathLibrary.cpp als deze al is geopend. Als dat niet het probleem is, dubbelklikt u in Solution Explorer op MathLibrary.cpp in de map Bronbestanden van het project MathLibrary om het te openen.
Vervang in de editor de inhoud van het
MathLibrary.cppbestand door de volgende code:// 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_; }
Compileer het DLL-bestand om te controleren of alles tot nu toe werkt. Als u wilt compileren, selecteert u Build Solution> in de menubalk. De DLL en gerelateerde compileruitvoer worden geplaatst in een map die direct onder de oplossingsmap heet Debug. Als u een release-build maakt, wordt de uitvoer geplaatst in een map met de naam Release. De uitvoer zou er ongeveer zo uit moeten zien:
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 ==========
Gefeliciteerd, u hebt een DLL gemaakt met behulp van Visual Studio! Vervolgens maakt u een client-app die gebruikmaakt van de functies die het DLL-bestand exporteert.
Een client-app maken die gebruikmaakt van het DLL-bestand
Wanneer u een DLL maakt, moet u nadenken over hoe client-apps deze kunnen gebruiken. Als u de functies wilt aanroepen of toegang wilt krijgen tot de gegevens die zijn geëxporteerd door een DLL, moet de broncode van de client de declaraties beschikbaar hebben tijdens het compileren. Tijdens de koppeling vereist de linker informatie om de functie-aanroepen of gegevenstoegang op te lossen. Een DLL levert deze informatie in een importbibliotheek, een bestand met informatie over het vinden van de functies en gegevens, in plaats van de werkelijke code. En tijdens runtime moet het DLL-bestand beschikbaar zijn voor de client, op een locatie die het besturingssysteem kan vinden.
Of het nu uw eigen project of van een derde partij is, uw client-app-project heeft verschillende stukjes informatie nodig om een DLL te gebruiken. Er moeten de headers worden gevonden die de DLL-exports declareren, de importbibliotheken voor de linker en het DLL-bestand zelf. Eén oplossing is het kopiëren van al deze bestanden naar uw clientproject. Voor DLL's van derden die waarschijnlijk niet veranderen terwijl uw client in ontwikkeling is, is deze methode mogelijk de beste manier om ze te gebruiken. Wanneer u echter ook de DLL bouwt, is het beter om duplicatie te voorkomen. Als u een lokale kopie maakt van DLL-bestanden die in ontwikkeling zijn, kunt u per ongeluk een headerbestand in de ene kopie wijzigen, maar niet de andere, of een verouderde bibliotheek gebruiken.
Als u niet-gesynchroniseerde code wilt voorkomen, stelt u het insluitingspad in uw clientproject in om de DLL-headerbestanden rechtstreeks vanuit uw DLL-project op te nemen. Stel ook het bibliotheekpad in uw clientproject in om de DLL-importbibliotheken uit het DLL-project op te nemen. Kopieer ten slotte de ingebouwde DLL van het DLL-project naar de uitvoermap van de client. Met deze stap kan uw client-app dezelfde DLL-code gebruiken die u bouwt.
Een client-app maken in Visual Studio
Selecteer Bestand>nieuw> op de menubalk Project om het dialoogvenster Een nieuwe project maken te openen.
Stel bovenaan het dialoogvenster Taal in op C++, stel Platform in op Windows en stel Projecttype in op Console.
Selecteer in de lijst met gefilterde projecttypen Console App en selecteer vervolgens Volgende.
Voer op de pagina Uw nieuwe project configurerenMathClient in het vak Projectnaam in om een naam voor het project op te geven. Laat de standaardwaarden voor de locatie - en oplossingsnaam staan . Stel oplossing in op Nieuwe oplossing maken. Schakel de optie Oplossing plaatsen en project in dezelfde map uit als deze is ingeschakeld.
Selecteer de knop Maken om het clientproject te maken.
Er wordt een simpel consoletoepassingsproject voor u gemaakt. De naam voor het hoofdbronbestand is hetzelfde als de projectnaam die u eerder hebt ingevoerd. In dit voorbeeld heeft deze de naam MathClient.cpp. U kunt het bouwen, maar het maakt nog geen gebruik van uw DLL.
Een client-app maken in Visual Studio 2017
Als u een C++-app wilt maken die gebruikmaakt van het DLL-bestand dat u hebt gemaakt, selecteert u Bestand>nieuw> op de menubalk Project.
Selecteer in het linkerdeelvenster van het dialoogvenster Nieuw projectWindows-bureaublad onder Geïnstalleerd> Visual C++. Selecteer windows-consoletoepassing in het middelste deelvenster. Voer MathClient in het vak Naam in. Behoud de standaardwaarden voor locatie - en oplossingsnamen . Stel oplossing in op Nieuwe oplossing maken. Selecteer Map maken voor oplossing als het niet is aangevinkt.
Selecteer OK om het client-app-project te maken.
Er wordt een simpel consoletoepassingsproject voor u gemaakt. De naam voor het hoofdbronbestand is hetzelfde als de projectnaam die u eerder hebt ingevoerd. In dit voorbeeld heeft deze de naam MathClient.cpp. U kunt het bouwen, maar het maakt nog geen gebruik van uw DLL.
Een client-app maken in Visual Studio 2015
Als u een C++-app wilt maken die gebruikmaakt van het DLL-bestand dat u hebt gemaakt, selecteert u Bestand>nieuw> op de menubalk Project.
Selecteer In het linkerdeelvenster van het dialoogvenster Nieuw projectWin32 onder Geïnstalleerde>sjablonen>visual C++. Selecteer in het middelste deelvenster Win32-consoletoepassing. Geef de naam op voor het project, MathClient, in het invoervak Naam . Laat de standaardwaarden voor de locatie - en oplossingsnaam staan . Stel oplossing in op Nieuwe oplossing maken. Selecteer Map maken voor oplossing als het niet is aangevinkt.
Selecteer de knop OK om het dialoogvenster Nieuw Project te sluiten en de wizard Win32-toepassing te starten. Selecteer op de pagina Overzicht van het dialoogvenster Wizard Win32-toepassing de knop Volgende .
Selecteer op de pagina Toepassingsinstellingen onder Toepassingstypeconsoletoepassing als deze nog niet is geselecteerd.
Selecteer Voltooien om het project te maken.
Wanneer de wizard is voltooid, maakt deze een minimaal project voor een consoletoepassing voor u. De naam voor het hoofdbronbestand is hetzelfde als de projectnaam die u eerder hebt ingevoerd. In dit voorbeeld heeft deze de naam MathClient.cpp. U kunt het bouwen, maar het maakt nog geen gebruik van uw DLL.
Als u vervolgens de MathLibrary-functies in uw broncode wilt aanroepen, moet uw project het MathLibrary.h bestand bevatten. U kunt dit headerbestand kopiëren naar uw client-app-project en het vervolgens als een bestaand item toevoegen aan het project. Deze methode kan een goede keuze zijn voor bibliotheken van derden. Als u echter tegelijkertijd aan de code voor uw DLL en uw client werkt, kunnen de headerbestanden niet meer worden gesynchroniseerd. Om dit probleem te voorkomen, stelt u het pad Extra inclusief mappen in uw project in om het pad naar de oorspronkelijke koptekst op te nemen.
Om de DLL-header aan uw inclusiepad toe te voegen
Klik met de rechtermuisknop op het knooppunt MathClient in Solution Explorer om het dialoogvenster Eigenschappenpagina's te openen.
Selecteer in de vervolgkeuzelijst Configuratiealle configuraties als deze nog niet is geselecteerd.
Selecteer in het linkerdeelvenster Configuratie-eigenschappen>C/C++>Algemeen.
Selecteer in het eigenschappenvenster het vervolgkeuzebesturingselement naast het bewerkingsvak Aanvullende include-mappen en selecteer vervolgens Bewerken.
Dubbelklik in het bovenste deelvenster van het dialoogvenster Extra mappen opnemen om een besturingselement voor bewerken in te schakelen. Of selecteer het mappictogram om een nieuw item aan te maken.
Geef in het bewerkingsvak het pad op naar het
MathLibrary.h-headerbestand. U kunt het weglatingsteken (...) gebruiken om naar de juiste map te bladeren.U kunt ook een relatief pad van uw clientbronbestanden invoeren naar de map die de DLL-headerbestanden bevat. Als u de aanwijzingen hebt gevolgd om uw clientproject in een afzonderlijke oplossing van het DLL-bestand te plaatsen, moet het relatieve pad er als volgt uitzien:
..\..\MathLibrary\MathLibraryAls uw DLL- en clientprojecten zich in dezelfde oplossing bevinden, kan het relatieve pad er als volgt uitzien:
..\MathLibraryWanneer de DLL- en clientprojecten zich in andere mappen bevinden, past u het relatieve pad aan zodat het overeenkomt. U kunt ook het knop met het beletselteken gebruiken om naar de map te bladeren.
Nadat u het pad naar het koptekstbestand hebt ingevoerd in het dialoogvenster Extra mappen opnemen , selecteert u OK. Selecteer OK in het dialoogvenster Eigenschappenpagina's om uw wijzigingen op te slaan.
U kunt nu het MathLibrary.h bestand opnemen en de functies gebruiken die het declareert in uw clienttoepassing. Vervang de inhoud van MathClient.cpp door deze code te gebruiken:
// 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;
}
Deze code kan worden gecompileerd, maar niet gekoppeld. Als u de client-app nu bouwt, worden in de foutenlijst verschillende LNK2019 fouten weergegeven. Dat komt doordat er gegevens ontbreken in uw project: u hebt niet opgegeven dat uw project nog afhankelijk is van de MathLibrary.lib bibliotheek. En u hebt de linker niet verteld hoe deze het bestand MathLibrary.lib kan vinden.
U kunt dit probleem oplossen door het bibliotheekbestand rechtstreeks naar uw client-app-project te kopiëren. De linker zou deze automatisch vinden en gebruiken. Als de bibliotheek en de client-app echter in ontwikkeling zijn, kan deze actie leiden tot wijzigingen in de ene kopie die niet in de andere worden weergegeven. Om dit probleem te voorkomen, stelt u de eigenschap Aanvullende afhankelijkheden in om het buildsysteem te laten weten dat uw project afhankelijk MathLibrary.libis. En stel een pad naar extra bibliotheekmappen in uw project in om het pad naar de oorspronkelijke bibliotheek op te nemen wanneer u een koppeling maakt.
De DLL-importbibliotheek toevoegen aan uw project
Klik met de rechtermuisknop op het knooppunt MathClient in Solution Explorer en selecteer Eigenschappen om het dialoogvenster Eigenschappenpagina's te openen.
Selecteer in de vervolgkeuzelijst Configuratiealle configuraties als deze nog niet is geselecteerd. Deze selectie zorgt ervoor dat eigenschapswijzigingen gelden voor zowel Debug- als Release-builds.
Selecteer in het linkerdeelvenster Configuratie-eigenschappen>Linker>Invoer. Selecteer in het eigenschappenvenster de vervolgkeuzelijst naast het invoervak Aanvullende afhankelijkheden en selecteer vervolgens Bewerken.
Voeg in het dialoogvenster
MathLibrary.libtoe aan de lijst in het bovenste bewerkbesturingselement.
Selecteer OK om terug te gaan naar het dialoogvenster Eigenschappenpagina's .
Selecteer in het linkerdeelvenster Configuratie-eigenschappen>linker>algemeen. Selecteer in het eigenschappenvenster het vervolgkeuzebesturingselement naast het bewerkingsvak Aanvullende bibliotheekmappen en selecteer vervolgens Bewerken.
Dubbelklik in het bovenste deelvenster van het dialoogvenster Extra bibliotheekmappen om een bewerkingsvak in te schakelen. Geef in het bewerkingsveld het pad op naar de locatie van het
MathLibrary.libbestand. Standaard bevindt deze zich in een map met de naam Debug rechtstreeks onder de DLL-oplossingsmap. Als u een release-build maakt, wordt het bestand in een map met de naam Release geplaatst. U kunt de$(IntDir)macro gebruiken zodat de linker uw DLL kan vinden, ongeacht welk type build u maakt. Als u de aanwijzingen hebt gevolgd om uw clientproject in een afzonderlijke oplossing van het DLL-project te plaatsen, moet het relatieve pad er als volgt uitzien:..\..\MathLibrary\$(IntDir)Als uw DLL- en clientprojecten zich op andere locaties bevinden, past u het relatieve pad aan zodat het overeenkomt.
Nadat u het pad naar het bibliotheekbestand in het dialoogvenster Aanvullende bibliotheekmappen hebt ingevoerd, selecteert u OK om terug te gaan naar het dialoogvenster Eigenschappenpagina's . Selecteer OK om de eigenschapswijzigingen op te slaan.
Uw client-app kan nu worden gecompileerd en gekoppeld, maar heeft nog steeds niet alles wat nodig is om uit te voeren. Wanneer het besturingssysteem uw app laadt, zoekt het naar de MathLibrary DLL. Als het DLL-bestand niet kan worden gevonden in bepaalde systeemmappen, het omgevingspad of de lokale app-map, mislukt het laden. Afhankelijk van het besturingssysteem ziet u een foutbericht als volgt:
Een manier om dit probleem te voorkomen, is door het DLL-bestand te kopiëren naar de map die het uitvoerbare bestand van de client bevat als onderdeel van het buildproces. U kunt een gebeurtenis na de build toevoegen aan uw project om een opdracht toe te voegen waarmee het DLL-bestand wordt gekopieerd naar de uitvoermap van uw build. Met de opdracht die u hier opgeeft, wordt het DLL-bestand alleen gekopieerd als deze ontbreekt of is gewijzigd. Er worden macro's gebruikt om te kopiëren naar en van de locaties voor foutopsporing of release, op basis van uw buildconfiguratie.
Het DLL-bestand kopiëren in een gebeurtenis na de build
Klik met de rechtermuisknop op het knooppunt MathClient in Solution Explorer en selecteer Eigenschappen om het dialoogvenster Eigenschappenpagina's te openen.
Selecteer alle configuraties in de vervolgkeuzelijst Configuratie als deze nog niet is geselecteerd.
Selecteer in het linkerdeelvenster Configuratie-eigenschappen>Buildgebeurtenissen>Post-Buildgebeurtenis.
Selecteer in het Eigenschappenvenster het bewerkingsveld in het veld Opdrachtregel. Als u de aanwijzingen hebt gevolgd om uw clientproject in een afzonderlijke oplossing van het DLL-project te plaatsen, voert u deze opdracht in:
xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"Als uw DLL- en clientprojecten zich in andere mappen bevinden, moet u het relatieve pad naar het DLL-bestand wijzigen zodat het klopt met de nieuwe locatie.
Selecteer OK om de wijzigingen in de projecteigenschappen op te slaan.
Uw client-app heeft nu alles wat nodig is om te bouwen en uit te voeren. Bouw de toepassing door Build Build>Solution te selecteren op de menubalk. In het venster Uitvoer in Visual Studio ziet u ongeveer het volgende voorbeeld, afhankelijk van uw versie van Visual Studio:
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 ==========
U hebt een toepassing gemaakt waarmee functies in uw DLL worden aangeroepen. Voer nu uw toepassing uit om te zien wat deze doet. Selecteer in de menubalk de optie Foutopsporing>starten zonder foutopsporing. Visual Studio opent een opdrachtvenster waarin het programma kan worden uitgevoerd. Het laatste deel van de uitvoer ziet er als volgt uit:
Druk op een willekeurige toets om het opdrachtvenster te sluiten.
Nu u een DLL en een clienttoepassing hebt gemaakt, kunt u experimenteren. Stel onderbrekingspunten in de code van de client-app in en voer de app uit in het foutopsporingsprogramma. Bekijk wat er gebeurt wanneer u stapt in een bibliotheekoproep. Voeg andere functies toe aan de bibliotheek of schrijf een andere client-app die gebruikmaakt van uw DLL.
Wanneer u uw app implementeert, moet u ook de DLL's implementeren die worden gebruikt. De eenvoudigste manier om de DLL's die u bouwt of die u opneemt van derden beschikbaar te maken, is door ze in dezelfde map te plaatsen als uw app. Deze benadering wordt ook wel implementatie van app-local genoemd. Zie Implementatie in Microsoft C++voor meer informatie over implementatie.