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) personalizzata scritta in Microsoft C++ (MSVC). Viene quindi illustrato 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 come modo 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 si creerà una DLL che implementa alcune funzioni matematiche. Si creerà quindi un'app console che usa le funzioni della DLL. Si otterrà anche un'introduzione ad alcune delle tecniche e delle convenzioni di programmazione usate nelle DLL di Windows.

In questa procedura dettagliata vengono illustrate le seguenti attività:

  • Creare un progetto di DLL in Visual Studio.

  • Aggiungere funzioni e variabili esportate nella DLL.

  • Creare un progetto di app console in Visual Studio.

  • Usare le funzioni e variabili importate dalla DLL nell'app console.

  • Eseguire l'app completata.

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. Diversamente da una libreria collegata staticamente, Windows connette le importazioni nell'app alle esportazioni in una DLL in fase di caricamento o in fase di esecuzione, invece di farlo 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 verranno presentate 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, mentre Windows collega l'app alla DLL in fase di caricamento. Questo collegamento consente all'app di chiamare le funzioni fornite dalla DLL proprio come le funzioni in una libreria collegata staticamente.

Questa procedura dettagliata non tratta alcune situazioni comuni. Il codice non mostra l'uso di DLL C++ da altri linguaggi di programmazione. Non mostra come creare una DLL solo risorsa o come usare il collegamento esplicito per caricare dll in fase di esecuzione anziché in fase di caricamento. Assicuratevi che sia possibile usare MSVC e Visual Studio per eseguire tutte queste operazioni.

Anche se il codice della DLL è scritto in C++, sono state 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 eseguire 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 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 ulteriori 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

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

    Visual Studio Installer, Desktop development with C++ workload.

  • Una copia di 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 dei concetti di base dell'uso dell'IDE di Visual Studio. Se si sono usate app desktop di Windows in precedenza, è probabilmente possibile riuscire a seguire. Per informazioni introduttive, vedere Panoramica delle funzionalità dell'IDE di Visual Studio.

  • Conoscenza delle nozioni di base del linguaggio C++. Non verranno comunque presentate procedure troppo complicate.

Nota

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 di DLL

In questo set di attività, si crea un progetto per la DLL, quindi si aggiunge codice e si compila il progetto. 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. Assicurarsi di avere selezionato la versione corretta nel controllo in alto a sinistra della pagina.

Per creare un progetto di DLL in Visual Studio 2019

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

    Screenshot of the Create a new project dialog with the Dynamic Link Library template highlighted.

  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 of the Solution Explorer window with the Math Library project highlighted.

Per creare un progetto di 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 Libreria a collegamento dinamico (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. Selezionare Crea directory per la soluzione se è deselezionata.

    Screenshot of the New Project dialog box showing Math Library in the Name text box.

  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 of the Solution Explorer window with the Math Library highlighted.

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 Installati>Modelli 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. Selezionare Crea directory per la soluzione se è deselezionata.

    Screenshot of the New Project dialog box showing Math Library in the Name text box.

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

    Screenshot of the Win32 Application Wizard Overview page.

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

    Screenshot of the Win32 Application Wizard Application Settings Page.

  5. Scegliere il pulsante Fine per creare il progetto.

Quando viene completata la soluzione, il progetto e i file di origine generati saranno visibili nella finestra Esplora soluzioni in Visual Studio.

Screenshot of the Solution Explorer window with the Math Library highlighted.

A questo punto la 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 of the Add New Item dialog with the C plus plus Header File template selected, and MathLibrary.h entered in the Name textbox.

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

    Screenshot of the empty MathLibrary.h file in the 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, dati due valori iniziali. Una chiamata a fibonacci_init(1, 1) genera la familiare sequenza di Fibonacci.

Si notino le istruzioni del preprocessore nella parte superiore 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 file con estensione cpp 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 è già aperta. In caso contrario, in Esplora soluzioni fare doppio clic su MathLibrary.cpp nella cartella File di origine del progetto MathLibrary per aprirlo.

  3. Nell'editor sostituire il contenuto del file MathLibrary.cpp 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 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 file MathLibrary.cpp 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 libreria di collegamento dinamico. Per compilare, scegliere Compila>Compila soluzione dalla 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 rilascio, l'output viene inserito in una cartella denominata Release. L'output dovrebbe essere simile al seguente:

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

È stata creata una DLL con Visual Studio. Nella prossima sezione si vedrà come creare 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 possono 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 una posizione individuabile dal sistema operativo.

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 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 vengano modificate durante lo sviluppo del client, questo metodo può rappresentare il modo migliore per usarle. Tuttavia, quando si crea 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 inoltre il percorso della libreria nel progetto client per includere le librerie di importazione DLL dal progetto di DLL. Infine, copiare la DLL compilata dal progetto DLL nella directory di output della compilazione client. Questo passaggio consente all'app client di usare lo stesso codice DLL che si compila.

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. Deselezionare Inserisci soluzione e progetto nella stessa directory , se selezionata.

    Screenshot of the Create a new project dialog box with the Console App option highlighted.

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

Viene creato automaticamente un progetto di applicazione console minimo. Il nome del file di origine principale è lo stesso nome del progetto immesso in precedenza. In questo esempio, il file è denominato MathClient.cpp. È possibile compilare il progetto, 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 Installati>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. Selezionare Crea directory per la soluzione se è deselezionata.

    Screenshot of the New Project dialog box with Installed > Visual C plus plus > Windows Desktop selected, Windows Console Application highlighted, and Math Client typed in the Name text box.

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

Viene creato automaticamente un progetto di applicazione console minimo. Il nome del file di origine principale è lo stesso nome del progetto immesso in precedenza. In questo esempio, il file è denominato MathClient.cpp. È possibile compilare il progetto, 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 in Installati>Modelli>Visual C++. Nel riquadro centrale, selezionare Progetto 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. Selezionare Crea directory per la soluzione se è deselezionata.

    Screenshot of the New Project dialog box with Installed > Templates > Visual C plus plus > Win32 selected, Win32 Console Application Visual C plus plus highlighted, and Math Client typed in the Name text box.

  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 Creazione guidata applicazione Win32 , scegliere il pulsante Avanti .

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

  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 è lo stesso nome del progetto immesso in precedenza. In questo esempio, il file è denominato MathClient.cpp. È possibile compilare il progetto, ma non usa ancora la DLL.

Successivamente, per chiamare le funzioni MathLibrary nel codice sorgente, il progetto deve includere il file MathLibrary.h . È possibile copiare questo file di intestazione nel progetto dell'app client e quindi aggiungerlo al progetto come elemento esistente. Questo metodo può essere una scelta ottimale 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. Nella casella di riepilogo a discesa Configurazione selezionare Tutte le configurazioni se non è già selezionata.

  3. Nel riquadro sinistro selezionare Proprietà>di configurazione C/C++>Generale.

  4. Nel riquadro delle proprietà selezionare il controllo elenco a discesa accanto alla casella di modifica Directory di inclusione aggiuntive e quindi scegliere Modifica.

    Screenshot of the Property Pages dialog showing the Edit command in the Additional Include Directories property drop-down.

  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 una nuova voce.

  6. Nel controllo 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 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 of the Additional Include Directories dialog showing the relative path to the MathLibrary directory.

  7. Dopo aver immesso il percorso del file di intestazione 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 file MathLibrary.h e usare le funzioni dichiarate nell'applicazione client. Sostituire il contenuto del file 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. Questo perché il progetto non contiene alcune informazioni: non è ancora stato specificato che il progetto ha una dipendenza dalla libreria MathLibrary.lib . E non hai detto al linker come trovare il file MathLibrary.lib .

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. Nella casella di riepilogo 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>Input del linker.> Nel riquadro delle proprietà selezionare il controllo elenco a discesa accanto alla casella di modifica Dipendenze aggiuntive e quindi scegliere Modifica.

    Screenshot of the Property Pages dialog showing the Edit command in the Linker > Input > Additional Dependencies property drop-down.

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

    Screenshot of the Additional Dependencies dialog showing the MathLibrary.lib file.

  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 elenco a discesa accanto alla casella di modifica Directory librerie aggiuntive e quindi scegliere Modifica.

    Screenshot of the Property Pages dialog showing the Edit command in the Linker > General > Additional Library Directories property drop-down.

  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 file MathLibrary.lib. 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 la DLL e i progetti client si trovano in altre posizioni, modificare il percorso relativo in modo che corrisponda.

    Screenshot of the Additional Library Directories dialog.

  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à.

È ora possibile compilare e collegare l'app client correttamente, ma ancora non include tutto ciò che serve 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, nel percorso di ambiente o nella directory dell'app locale, il caricamento ha esito negativo. A seconda del sistema operativo, verrà visualizzato un messaggio di errore simile al seguente:

Screenshot of the error dialog, MathLibrary DLL not found.

Un modo per evitare questo problema consiste nel copiare la DLL nella directory che contiene il file eseguibile del 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 della compilazione. Il comando specificato qui copia la DLL solo se manca o è stata modificata. Usa macro per copiare da e verso i percorsi debug o versione, in base alla configurazione della compilazione.

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. Nella casella a discesa Configurazione selezionare Tutte le configurazioni se non è già selezionato.

  3. Nel riquadro sinistro selezionare Proprietà>di configurazione Eventi>di compilazione 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 of the Property Pages dialog showing the post build event command line property.

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

A questo punto l'app client include tutto il necessario per la compilazione e l'esecuzione. Compilare l'applicazione scegliendo Compila>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 ==========

È stata completata la creazione di un'applicazione che chiama le funzioni nella DLL. Eseguire ora l'applicazione per vederne le funzioni. Sulla barra dei menu scegliere Debug>Avvia senza eseguire debug. Visual Studio apre una finestra di comando in cui eseguire il programma. L'ultima parte dell'output sarà simile al seguente:

Screenshot of the command window output when you start the client app without debugging.

Premere un tasto qualsiasi per chiudere la finestra di comando.

Ora che sono state create una DLL e un'applicazione client, è possibile sperimentarle. Provare a impostare punti di interruzione nel codice dell'app client ed eseguire l'app nel debugger. Vedere cosa accade quando si esegue una chiamata della 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 creare le DLL compilate o incluse da terze parti è inserirle nella stessa directory dell'app. È nota come distribuzione locale dell'app. Per altre informazioni sulla distribuzione, vedere Deployment in Visual C++.

Vedi anche

Chiamata di funzioni DLL da applicazioni Visual Basic