Condividi tramite


Procedura dettagliata: Creare e usare la propria libreria di collegamento dinamico (C++)

Questa procedura dettagliata illustra come usare l'IDE di Visual Studio per creare una libreria a collegamento dinamico (DLL) scritta in Microsoft C++ (MSVC) e come usare la DLL da un'altra app C++. Le DLL, note anche come librerie condivise nei sistemi operativi basati su UNIX, sono uno dei tipi più utili di componenti di Windows. È possibile usarli per condividere codice e risorse e ridurre le dimensioni delle app. Le DLL possono anche semplificare il servizio ed estendere le app.

In questa procedura dettagliata viene creata una DLL che implementa alcune funzioni matematiche. Si crea quindi un'app console che usa le funzioni della DLL. Si ottiene anche un'introduzione ad alcune delle tecniche e delle convenzioni di programmazione usate nelle DLL di Windows.

Questa procedura dettagliata illustra i passaggi seguenti:

  • Creare un progetto DLL in Visual Studio.
  • Aggiungere funzioni e variabili esportate alla DLL.
  • Creare un progetto di app console in Visual Studio.
  • Usare le funzioni e le variabili importate dalla DLL nell'app console.
  • Eseguire l'applicazione completa.

Come una libreria collegata in modo statico, una DLL esporta variabili, funzioni e risorse in base al nome. Un'app client importa i nomi per usare tali variabili, funzioni e risorse. A differenza di una libreria collegata in modo statico, Windows connette le importazioni nell'app alle esportazioni in una DLL in fase di caricamento o in fase di esecuzione, anziché connetterle in fase di collegamento. Windows richiede informazioni aggiuntive che non fanno parte del modello di compilazione C++ standard per stabilire queste connessioni. Il compilatore MSVC implementa alcune estensioni specifiche di Microsoft per C++ per fornire queste informazioni aggiuntive. Queste estensioni vengono illustrate man mano che si procede.

Questa procedura dettagliata crea due soluzioni di Visual Studio: una che compila la DLL e una che compila l'app client. La DLL usa la convenzione di chiamata C. Può essere chiamato dalle app scritte in altri linguaggi di programmazione, purché la piattaforma, le convenzioni di chiamata e le convenzioni di collegamento corrispondano. L'app client usa il collegamento implicito, in cui Windows collega l'app alla DLL in fase di caricamento. Questo collegamento consente all'app di chiamare le funzioni fornite dalla DLL esattamente come le funzioni in una libreria collegata in modo statico.

Questa guida non illustra alcune situazioni tipiche. Il codice non mostra l'uso di DLL C++ da altri linguaggi di programmazione. Non mostra come creare una DLL contenente solo risorse o come usare il collegamento esplicito per caricare le DLL a runtime anziché a caricamento. Assicuratevi che sia possibile usare MSVC e Visual Studio per eseguire tutte queste operazioni.

Anche se il codice della DLL è scritto in C++, vengono usate interfacce di tipo C per le funzioni esportate. Esistono due motivi principali: in primo luogo, molti altri linguaggi supportano le importazioni di funzioni in stile C. L'app client non deve essere scritta in C++. In secondo luogo, evita alcune insidie comuni correlate alle classi esportate e alle funzioni membro. È facile commettere errori difficili da diagnosticare durante l'esportazione delle classi, poiché tutto ciò a cui si fa riferimento all'interno di una dichiarazione di classe deve avere anche un'istanza che viene esportata. Questa restrizione si applica alle DLL, ma non alle librerie statiche. Se le classi sono di tipo plain-old-data, non è consigliabile riscontrare questo problema.

Per collegamenti a altre informazioni sulle DLL, vedere Creare DLL C/C++ in Visual Studio. Per altre informazioni sul collegamento implicito e sul collegamento esplicito, vedere Determinare il metodo di collegamento da usare. Per informazioni sulla creazione di DLL C++ da usare con linguaggi di programmazione che usano convenzioni di collegamento al linguaggio C, vedere Esportazione di funzioni C++ da usare nei file eseguibili in linguaggio C. Per informazioni su come creare DLL da usare con i linguaggi .NET, vedere Chiamata di funzioni DLL da applicazioni Visual Basic.

Prerequisiti

  • Microsoft Windows 7 o versione successiva. È consigliabile usare la versione più recente di Windows per un'esperienza di sviluppo ottimale.
  • Visual Studio. Per informazioni su come scaricare e installare Visual Studio, vedere Installare Visual Studio. Quando si esegue il programma di installazione, assicurarsi che il carico di lavoro Sviluppo di applicazioni desktop con C++ sia selezionato. Non preoccuparti se questo carico di lavoro non è stato installato durante l'installazione di Visual Studio. È possibile eseguire di nuovo il programma di installazione e installarlo ora.

    Screenshot del programma di installazione di Visual Studio, Sviluppo di applicazioni desktop con carico di lavoro C++.

  • Visual Studio. Per informazioni su come scaricare e installare Visual Studio 2015, vedere Installare Visual Studio 2015. Usare un'installazione personalizzata per installare il compilatore e gli strumenti C++, perché non sono installati per impostazione predefinita.
  • Conoscenza delle nozioni di base sull'uso dell'IDE di Visual Studio. Se hai usato le app desktop di Windows in precedenza, probabilmente puoi tenerti al passo. Per un'introduzione, vedere Presentazione delle funzionalità dell'IDE di Visual Studio.

  • Familiarità con il linguaggio C++. Non preoccuparti, non facciamo niente di troppo complicato.

Annotazioni

Questa procedura dettagliata presuppone che si usi Visual Studio 2017 versione 15.9 o successiva. Alcune versioni precedenti di Visual Studio 2017 presentavano difetti nei modelli di codice o usavano finestre di dialogo diverse dell'interfaccia utente. Per evitare problemi, usare il programma di installazione di Visual Studio per aggiornare Visual Studio 2017 alla versione 15.9 o successiva.

Creare il progetto DLL

Nel set di attività seguente si crea un progetto per la DLL, si aggiunge il codice e lo si compila. Per iniziare, avviare l'IDE di Visual Studio e accedere se necessario. Le istruzioni variano leggermente a seconda della versione di Visual Studio in uso. Per visualizzare i passaggi per la versione preferita di Visual Studio, usare il selettore della versione disponibile nella parte superiore del sommario in questa pagina.

Per creare un progetto DLL in Visual Studio

  1. Sulla barra dei menu scegliere File>Nuovo>Progetto per aprire la finestra di dialogo Crea nuovo progetto.

    Screenshot della finestra di dialogo Crea un nuovo progetto con il modello di libreria a collegamento dinamico evidenziato.

  2. Nella parte superiore della finestra di dialogo impostare Linguaggio su C++, impostare Piattaforma su Windows e impostare Tipo di progetto su Libreria.

  3. Nell'elenco filtrato dei tipi di progetto selezionare Libreria a collegamento dinamico (DLL) e quindi scegliere Avanti.

  4. Nella pagina Configura il nuovo progetto immettere MathLibrary nella casella Nome progetto per specificare un nome per il progetto. Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Deselezionare Inserisci soluzione e progetto nella stessa directory , se selezionata.

  5. Scegliere il pulsante Crea per creare il progetto.

Quando viene creata la soluzione, è possibile visualizzare i file di progetto e di origine generati nella finestra Esplora soluzioni in Visual Studio.

Screenshot della finestra Esplora soluzioni con il progetto MathLibrary evidenziato.

Per creare un progetto DLL in Visual Studio 2017

  1. Sulla barra dei menu scegliere File>Nuovo>Progetto per aprire la finestra di dialogo Nuovo progetto.

  2. Nel riquadro sinistro della finestra di dialogo Nuovo progetto selezionare Installato>Visual C++>Windows Desktop. Nel riquadro centrale selezionare Dynamic-Link Libreria (DLL). Immettere MathLibrary nella casella Nome per specificare un nome per il progetto. Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Seleziona Crea directory per la soluzione se è deselezionata.

    Screenshot della finestra di dialogo Nuovo progetto in Visual Studio 2017 che mostra la libreria matematica nella casella di testo Nome.

  3. Scegliere il pulsante OK per creare il progetto.

Quando viene creata la soluzione, è possibile visualizzare i file di progetto e di origine generati nella finestra Esplora soluzioni in Visual Studio.

Screenshot della finestra Esplora soluzioni in Visual Studio 2017 con la libreria matematica evidenziata.

Per creare un progetto DLL in Visual Studio 2015 e versioni precedenti

  1. Nella barra dei menu scegliere File>Nuovo>Progetto.

  2. Nel riquadro sinistro della finestra di dialogo Nuovo progetto espandere Modelli installati> e selezionare Visual C++, quindi nel riquadro centrale selezionare Applicazione console Win32. Immettere MathLibrary nella casella di modifica Nome per specificare un nome per il progetto. Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Se l'opzione Crea directory per la soluzione non è selezionata, selezionala.

    Screenshot della finestra di dialogo Nuovo progetto in Visual Studio 2015 che mostra MathLibrary nella casella di testo Nome.

  3. Scegliere il pulsante OK per chiudere la finestra di dialogo Nuovo progetto e avviare la Creazione guidata applicazione Win32.

    Screenshot della pagina Panoramica della Creazione guidata dell'applicazione Win32.

  4. Fare clic su Avanti. Nella pagina Impostazioni applicazione , in Tipo di applicazione, selezionare DLL.

    Screenshot della pagina della Procedura guidata Applicazione Win32 - Impostazioni applicazione.

  5. Scegliere il pulsante Fine per creare il progetto.

Al termine della procedura guidata, è possibile visualizzare i file di progetto e di origine generati nella finestra Esplora soluzioni in Visual Studio.

Screenshot della finestra Esplora soluzioni in Visual Studio 2015 con MathLibrary evidenziato.

Al momento, questa DLL non fa molto. Successivamente, si creerà un file di intestazione per dichiarare le funzioni esportate dalla DLL e quindi si aggiungeranno le definizioni di funzione alla DLL per renderlo più utile.

Per aggiungere un file di intestazione alla DLL

  1. Per creare un file di intestazione per le funzioni, nella barra dei menu scegliere Progetto>Aggiungi nuovo elemento.

  2. Nel riquadro sinistro della finestra di dialogo Aggiungi nuovo elemento selezionare Visual C++. Nel riquadro centrale selezionare File di intestazione (.h). Specificare MathLibrary.h come nome per il file di intestazione.

    Screenshot della finestra di dialogo Aggiungi nuovo elemento con il modello C più file di intestazione selezionato e MathLibrary.h immesso nella casella di testo Nome.

  3. Scegliere il pulsante Aggiungi per generare un file di intestazione vuoto, visualizzato in una nuova finestra dell'editor.

    Screenshot del file di MathLibrary.h vuoto nell'editor.

  4. Sostituire il contenuto del file di intestazione con questo codice:

    // 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();
    

Questo file di intestazione dichiara alcune funzioni per produrre una sequenza di Fibonacci generalizzata, in base a due valori iniziali. Una chiamata a fibonacci_init(1, 1) genera la sequenza di numeri di Fibonacci familiare.

Si notino le istruzioni del preprocessore all'inizio del file. Il nuovo modello di progetto per un progetto DLL aggiunge <PROJECTNAME>_EXPORTS alle macro del preprocessore definite. In questo esempio Visual Studio definisce MATHLIBRARY_EXPORTS quando viene compilato il progetto DLL MathLibrary.

Quando la MATHLIBRARY_EXPORTS macro è definita, la MATHLIBRARY_API macro imposta il __declspec(dllexport) modificatore nelle dichiarazioni di funzione. Questo modificatore indica al compilatore e al linker di esportare una funzione o una variabile dalla DLL da usare da altre applicazioni. Quando MATHLIBRARY_EXPORTS non è definito, ad esempio, quando il file di intestazione viene incluso da un'applicazione client, MATHLIBRARY_API applica il __declspec(dllimport) modificatore alle dichiarazioni. Questo modificatore ottimizza l'importazione della funzione o della variabile in un'applicazione. Per altre informazioni, vedere dllexport, dllimport.

Per aggiungere un'implementazione alla DLL

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo File di origine e scegliere Aggiungi>nuovo elemento. Creare un nuovo .cpp file denominato MathLibrary.cpp, nello stesso modo in cui è stato aggiunto un nuovo file di intestazione nel passaggio precedente.

  2. Nella finestra dell'editor, selezionare la scheda MathLibrary.cpp se questa è già aperta. In caso contrario, in Esplora soluzioni fare doppio clic MathLibrary.cpp nella cartella File di origine del progetto MathLibrary per aprirlo.

  3. Nell'editor sostituire il contenuto del MathLibrary.cpp file con il codice seguente:

    // 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_;
    }
    
  1. Nella finestra dell'editor selezionare la scheda per MathLibrary.cpp se è già aperta. In caso contrario, in Esplora soluzioni fare doppio clic su MathLibrary.cpp nella cartella File di origine del progetto MathLibrary per aprirlo.

  2. Nell'editor sostituire il contenuto del MathLibrary.cpp file con il codice seguente:

    // 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_;
    }
    

Per verificare che tutto funzioni finora, compilare la DLL. Per la compilazione, scegliere Compila>soluzione nella barra dei menu. La DLL e l'output del compilatore correlato vengono inseriti in una cartella denominata Debug direttamente sotto la cartella della soluzione. Se si crea una build di versione, l'output viene inserito in una cartella denominata Release. L'output dovrebbe essere simile a questo:

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 ==========

Congratulazioni, hai creato una DLL utilizzando Visual Studio! Si creerà quindi un'app client che usa le funzioni esportate dalla DLL.

Creare un'app client che usa la DLL

Quando si crea una DLL, considerare il modo in cui le app client potrebbero usarla. Per chiamare le funzioni o accedere ai dati esportati da una DLL, il codice sorgente del client deve disporre delle dichiarazioni disponibili in fase di compilazione. In fase di collegamento, il linker richiede informazioni per risolvere le chiamate di funzione o gli accessi ai dati. Una DLL fornisce queste informazioni in una libreria di importazione, un file che contiene informazioni su come trovare le funzioni e i dati, anziché il codice effettivo. E in fase di esecuzione, la DLL deve essere disponibile per il client, in un percorso che il sistema operativo può trovare.

Indipendentemente dal fatto che si tratti di un progetto di terze parti, il progetto dell'app client richiede diverse informazioni per usare una DLL. Deve trovare le intestazioni che dichiarano le esportazioni della DLL, le librerie di importazione per il linker e la DLL stessa. Una soluzione consiste nel copiare tutti questi file nel progetto client. Per le DLL di terze parti che è improbabile cambino mentre il client è in fase di sviluppo, questo metodo potrebbe essere il modo migliore per usarle. Tuttavia, quando si compila anche la DLL, è preferibile evitare la duplicazione. Se si crea una copia locale di file DLL in fase di sviluppo, è possibile modificare accidentalmente un file di intestazione in una copia, ma non l'altro, o usare una libreria non aggiornata.

Per evitare il codice non sincronizzato, è consigliabile impostare il percorso di inclusione nel progetto client per includere i file di intestazione DLL direttamente dal progetto DLL. Impostare anche il percorso della libreria nel progetto client per includere le librerie di importazione DLL dal progetto DLL. Infine, copiare la DLL compilata dal progetto DLL nella directory di output del client. Questo passaggio consente all'app client di usare lo stesso codice DLL compilato.

Per creare un'app client in Visual Studio

  1. Nella barra dei menu scegliere File>nuovo>progetto per aprire la finestra di dialogo Crea un nuovo progetto .

  2. Nella parte superiore della finestra di dialogo impostare Linguaggio su C++ , impostare Piattaforma su Windows e impostare Tipo di progetto su Console.

  3. Nell'elenco filtrato dei tipi di progetto scegliere App console e quindi scegliere Avanti.

  4. Nella pagina Configura il nuovo progetto immettere MathClient nella casella Nome progetto per specificare un nome per il progetto. Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Deseleziona Inserire soluzione e progetto nella stessa directory se è selezionato.

    Screenshot della finestra di dialogo Crea un nuovo progetto con l'opzione App console evidenziata.

  5. Scegliere il pulsante Crea per creare il progetto client.

Ti è stato creato un progetto di applicazione console minimalista. Il nome del file di origine principale corrisponde al nome del progetto immesso in precedenza. In questo esempio è denominato MathClient.cpp. È possibile compilarlo, ma non usa ancora la DLL.

Per creare un'app client in Visual Studio 2017

  1. Per creare un'app C++ che usa la DLL creata, nella barra dei menu scegliere File>Nuovo>progetto.

  2. Nel riquadro sinistro della finestra di dialogo Nuovo progetto selezionare Desktop di Windows in Installato>Visual C++. Nel riquadro centrale selezionare Applicazione console di Windows. Specificare il nome del progetto MathClient nella casella di modifica Nome . Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Contrassegna Crea directory per la soluzione se non è selezionata.

    Screenshot della finestra di dialogo Nuovo progetto con Applicazione console di Windows evidenziata e Math Client digitato nella casella di testo Nome.

  3. Scegliere OK per creare il progetto dell'app client.

Viene creato per te un progetto minimo di applicazione console. Il nome del file di origine principale corrisponde al nome del progetto immesso in precedenza. In questo esempio è denominato MathClient.cpp. È possibile compilarlo, ma non usa ancora la DLL.

Per creare un'app client in Visual Studio 2015

  1. Per creare un'app C++ che usa la DLL creata, nella barra dei menu scegliere File>Nuovo>progetto.

  2. Nel riquadro sinistro della finestra di dialogo Nuovo progetto selezionare Win32 inModelli>installati>Visual C++. Nel riquadro centrale selezionare Applicazione console Win32. Specificare il nome del progetto MathClient nella casella di modifica Nome . Lasciare i valori predefiniti Percorso e Nome soluzione . Impostare Soluzione su Crea nuova soluzione. Seleziona Crea directory per la soluzione se non è selezionata.

    Screenshot della finestra di dialogo Nuovo progetto con Win32 Console Application Visual C++ evidenziato e Math Client digitato nella casella di testo Nome.

  3. Scegliere il pulsante OK per chiudere la finestra di dialogo Nuovo progetto e avviare la Creazione guidata applicazione Win32. Nella pagina Panoramica della finestra di dialogo della Procedura guidata applicazione Win32, scegliere il pulsante Avanti.

  4. Nella pagina Impostazioni applicazione , in Tipo di applicazione selezionare Applicazione console , se non è già selezionata.

  5. Scegliere il pulsante Fine per creare il progetto.

Al termine della procedura guidata, viene creato automaticamente un progetto di applicazione console minimo. Il nome del file di origine principale corrisponde al nome del progetto immesso in precedenza. In questo esempio è denominato MathClient.cpp. È possibile compilarlo, ma non usa ancora la DLL.

Successivamente, per chiamare le funzioni MathLibrary nel codice sorgente, il progetto deve includere il MathLibrary.h file. È possibile copiare questo file di intestazione nel progetto dell'app client, quindi aggiungerlo al progetto come elemento esistente. Questo metodo può essere una buona scelta per le librerie di terze parti. Tuttavia, se si sta lavorando al codice per la DLL e il client contemporaneamente, i file di intestazione potrebbero non essere sincronizzati. Per evitare questo problema, impostare il percorso Directory di inclusione aggiuntive nel progetto per includere il percorso dell'intestazione originale.

Per aggiungere l'intestazione DLL al percorso di inclusione

  1. Fare clic con il pulsante destro del mouse sul nodo MathClient in Esplora soluzioni per aprire la finestra di dialogo Pagine delle proprietà .

  2. Nell'elenco a discesa Configurazione selezionare Tutte le configurazioni se non è già selezionata.

  3. Nel riquadro sinistro selezionare> di configurazione>Generale.

  4. Nel pannello delle proprietà, selezionare il menu a discesa accanto alla casella Directory di inclusione aggiuntive e quindi scegliere Modifica.

    Screenshot della finestra di dialogo Pagine delle proprietà che mostra il comando Modifica nel menu a tendina della proprietà Directory di inclusione aggiuntive.

  5. Fare doppio clic nel riquadro superiore della finestra di dialogo Directory di inclusione aggiuntive per abilitare un controllo di modifica. In alternativa, scegliere l'icona della cartella per creare un nuovo elemento.

  6. Nella casella di modifica, specificare il percorso del file di intestazione MathLibrary.h. È possibile scegliere il controllo con i puntini di sospensione (...) per passare alla cartella corretta.

    È anche possibile immettere un percorso relativo dai file di origine del client alla cartella che contiene i file di intestazione DLL. Se sono state seguite le istruzioni per inserire il progetto client in una soluzione separata dalla DLL, il percorso relativo dovrebbe essere simile al seguente:

    ..\..\MathLibrary\MathLibrary

    Se la DLL e i progetti client si trovano nella stessa soluzione, il percorso relativo potrebbe essere simile al seguente:

    ..\MathLibrary

    Quando la DLL e i progetti client si trovano in altre cartelle, modificare il percorso relativo in modo che corrisponda. In alternativa, usare il controllo con i puntini di sospensione per cercare la cartella.

    Screenshot della finestra di dialogo delle Directory di Inclusione Aggiuntive che mostra il percorso relativo alla directory MathLibrary.

  7. Dopo aver immesso il percorso del file header nella finestra di dialogo Directory di inclusione aggiuntive, scegliere il pulsante OK. Nella finestra di dialogo Pagine delle proprietà scegliere il pulsante OK per salvare le modifiche.

È ora possibile includere il MathLibrary.h file e usare le funzioni dichiarate nell'applicazione client. Sostituire il contenuto di MathClient.cpp usando questo codice:

// 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;
}

Questo codice può essere compilato, ma non collegato. Se si compila l'app client ora, l'elenco degli errori mostra diversi errori LNK2019. Ciò è dovuto al fatto che il progetto non contiene alcune informazioni: non è stato ancora specificato che il progetto ha una dipendenza dalla MathLibrary.lib libreria. E non hai detto al linker come trovare il MathLibrary.lib file.

Per risolvere questo problema, è possibile copiare il file di libreria direttamente nel progetto dell'app client. Il linker lo troverà e lo userà automaticamente. Tuttavia, se sia la libreria che l'app client sono in fase di sviluppo, ciò potrebbe causare modifiche in una copia non visualizzata nell'altra. Per evitare questo problema, è possibile impostare la proprietà Dipendenze aggiuntive per indicare al sistema di compilazione che il progetto dipende da MathLibrary.lib. Inoltre, è possibile impostare un percorso Directory di libreria aggiuntive nel progetto per includere il percorso della libreria originale quando si collega.

Per aggiungere la libreria di importazione DLL al progetto

  1. Fare clic con il pulsante destro del mouse sul nodo MathClient in Esplora soluzioni e scegliere Proprietà per aprire la finestra di dialogo Pagine delle proprietà .

  2. Nell'elenco a discesa Configurazione selezionare Tutte le configurazioni se non è già selezionata. Garantisce che le modifiche alle proprietà vengano applicate sia alle build di debug che a quella di rilascio.

  3. Nel riquadro sinistro selezionare Proprietà di configurazione>Linker>Input. Nel riquadro delle proprietà selezionare il controllo a discesa accanto alla casella di modifica Dipendenze aggiuntive e quindi scegliere Modifica.

    Screenshot della finestra di dialogo delle Pagine delle proprietà sotto Input che mostra il comando Modifica nel menu a tendina della proprietà Dipendenze aggiuntive.

  4. Nella finestra di dialogo Dipendenze aggiuntive aggiungere MathLibrary.lib all'elenco nel controllo di modifica superiore.

    Screenshot della finestra di dialogo Dipendenze aggiuntive che mostra il file MathLibrary.lib.

  5. Scegliere OK per tornare alla finestra di dialogo Pagine delle proprietà .

  6. Nel riquadro sinistro selezionare Proprietà di configurazione>Linker>Generale. Nel riquadro delle proprietà selezionare il controllo a discesa accanto alla casella di modifica Directory librerie aggiuntive e quindi scegliere Modifica.

    Screenshot della finestra di dialogo Pagine delle proprietà sotto Generale che mostra il comando modifica nell'elenco a discesa delle directory aggiuntive della libreria.

  7. Fare doppio clic nel riquadro superiore della finestra di dialogo Directory librerie aggiuntive per abilitare un controllo di modifica. Nel controllo di modifica specificare il percorso del MathLibrary.lib file. Per impostazione predefinita, si trova in una cartella denominata Debug direttamente nella cartella della soluzione DLL. Se si crea una build di versione, il file viene inserito in una cartella denominata Release. È possibile usare la $(IntDir) macro in modo che il linker possa trovare la DLL, indipendentemente dal tipo di compilazione creato. Se sono state seguite le istruzioni per inserire il progetto client in una soluzione separata dal progetto DLL, il percorso relativo dovrebbe essere simile al seguente:

    ..\..\MathLibrary\$(IntDir)

    Se le DLL e i progetti client si trovano in altre posizioni, adegua il percorso relativo in modo che corrisponda.

    Screenshot della finestra di dialogo delle directory librerie aggiuntive.

  8. Dopo aver immesso il percorso del file di libreria nella finestra di dialogo Directory librerie aggiuntive , scegliere il pulsante OK per tornare alla finestra di dialogo Pagine delle proprietà . Scegliere OK per salvare le modifiche alle proprietà.

L'app client può ora compilare e collegare correttamente, ma non ha ancora tutti gli elementi necessari per l'esecuzione. Quando il sistema operativo carica l'app, cerca la DLL MathLibrary. Se non riesce a trovare la DLL in determinate directory di sistema, il percorso dell'ambiente o la directory dell'app locale, il caricamento non riesce. A seconda del sistema operativo, verrà visualizzato un messaggio di errore simile al seguente:

Screenshot della finestra di dialogo di errore, DLL MathLibrary non trovata.

Un modo per evitare questo problema consiste nel copiare la DLL nella directory contenente il file eseguibile client come parte del processo di compilazione. È possibile aggiungere un evento di post-compilazione al progetto per aggiungere un comando che copia la DLL nella directory di output di compilazione. Il comando specificato qui copia la DLL solo se manca o è stata modificata. Usa macro per copiare da e verso le posizioni Debug o Release, in base alla tua configurazione di build.

Per copiare la DLL in un evento di post-compilazione

  1. Fare clic con il pulsante destro del mouse sul nodo MathClient in Esplora soluzioni e scegliere Proprietà per aprire la finestra di dialogo Pagine delle proprietà .

  2. Nell'elenco a discesa Configurazione selezionare Tutte le configurazioni se non è già selezionato.

  3. Nel riquadro sinistro selezionare Proprietà di Configurazione>Eventi di Compilazione>Evento Post-Compilazione.

  4. Nel riquadro delle proprietà selezionare il controllo di modifica nel campo Riga di comando . Se sono state seguite le istruzioni per inserire il progetto client in una soluzione separata dal progetto DLL, immettere questo comando:

    xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"

    Se la DLL e i progetti client si trovano in altre directory, modificare il percorso relativo alla DLL in modo che corrisponda.

    Screenshot della finestra di dialogo Pagine delle proprietà che mostra la proprietà della riga di comando dell'evento post-compilazione.

  5. Scegliere il pulsante OK per salvare le modifiche apportate alle proprietà del progetto.

Ora l'app client ha tutto il necessario per compilare ed eseguire. Compilare l'applicazione scegliendo Compila>soluzione nella barra dei menu. La finestra Output in Visual Studio dovrebbe avere un aspetto simile all'esempio seguente a seconda della versione di 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 ==========

Complimenti, hai creato un'applicazione che chiama le funzioni nella tua DLL. Eseguire ora l'applicazione per visualizzare le operazioni eseguite. Sulla barra dei menu scegliere Debug>Avvia senza eseguire il debug. Visual Studio apre una finestra di comando in cui eseguire il programma. L'ultima parte dell'output dovrebbe essere simile alla seguente:

Screenshot dell'output della finestra di comando quando si avvia l'app client senza eseguire il debug.

Premere un tasto qualsiasi per chiudere la finestra di comando.

Dopo aver creato una DLL e un'applicazione client, è possibile sperimentare. Provare a impostare punti di interruzione nel codice dell'app client ed eseguire l'app nel debugger. Vedere cosa accade quando si accede a una chiamata alla libreria. Aggiungere altre funzioni alla libreria o scrivere un'altra app client che usa la DLL.

Quando si distribuisce l'app, è necessario distribuire anche le DLL usate. Il modo più semplice per rendere disponibili le DLL che costruisci o che includi da terze parti è inserirle nella stessa directory dell'app. È nota come distribuzione locale dell'app. Per altre informazioni sulla distribuzione, vedere Distribuzione in Microsoft C++.

Vedere anche