Partilhar via


Passo a passo: Criar e usar sua própria biblioteca de vínculo dinâmico (C++)

Este passo a passo explica como usar o IDE do Visual Studio para criar sua própria biblioteca de vínculo dinâmico (DLL) escrita em Microsoft C++ (MSVC) e como usar a DLL de outro aplicativo C++. As DLLs, também conhecidas como bibliotecas compartilhadas em sistemas operacionais baseados em UNIX, são um dos tipos mais úteis de componentes do Windows. Você pode usá-los para compartilhar código e recursos e para reduzir o tamanho de seus aplicativos. As DLLs podem até facilitar a manutenção e a extensão de seus aplicativos.

Neste passo a passo, você cria uma DLL que implementa algumas funções matemáticas. Em seguida, você cria um aplicativo de console que usa as funções da DLL. Você também obtém uma introdução a algumas das técnicas e convenções de programação usadas em DLLs do Windows.

Este passo a passo abrange as seguintes etapas:

  • Crie um projeto DLL no Visual Studio.
  • Adicione funções e variáveis exportadas à DLL.
  • Crie um projeto de aplicativo de console no Visual Studio.
  • Use as funções e variáveis importadas da DLL no aplicativo de console.
  • Execute o aplicativo concluído.

Como uma biblioteca vinculada estaticamente, uma DLL exporta variáveis, funções e recursos pelo nome. Um aplicativo cliente importa os nomes para usar essas variáveis, funções e recursos. Ao contrário de uma biblioteca ligada estaticamente, o Windows conecta as importações na sua aplicação às exportações numa DLL no momento do carregamento ou no momento da execução, em vez de as conectar no momento da ligação. O Windows requer informações adicionais que não fazem parte do modelo de compilação C++ padrão para fazer essas conexões. O compilador MSVC implementa algumas extensões específicas da Microsoft para C++ para fornecer essas informações extras. Explicamos essas extensões à medida que avançamos.

Este passo a passo cria duas soluções do Visual Studio: uma que cria a DLL e outra que cria o aplicativo cliente. A DLL usa a convenção de chamada C. Ele pode ser chamado a partir de aplicativos escritos em outras linguagens de programação, desde que a plataforma, as convenções de chamada e as convenções de vinculação coincidam. O aplicativo cliente usa vinculação implícita, onde o Windows vincula o aplicativo à DLL no momento do carregamento. Essa vinculação permite que o aplicativo chame as funções fornecidas pela DLL, assim como as funções em uma biblioteca vinculada estaticamente.

Este passo a passo não cobre algumas situações comuns. O código não mostra o uso de DLLs C++ por outras linguagens de programação. Ele não mostra como criar uma DLL apenas de recursos, ou como usar ligação explícita para carregar DLLs em tempo de execução em vez de em tempo de carregamento. Tenha certeza, você pode usar MSVC e Visual Studio para fazer todas essas coisas.

Embora o código da DLL seja escrito em C++, usamos interfaces de estilo C para as funções exportadas. Há duas razões principais para isso: primeiro, muitos outros idiomas suportam importações de funções de estilo C. O aplicativo cliente não precisa ser escrito em C++. Em segundo lugar, evita algumas armadilhas comuns relacionadas a classes exportadas e funções de membros. É fácil cometer erros difíceis de diagnosticar ao exportar classes, uma vez que tudo o que é referido numa declaração de classe tem de ter uma instanciação que também é exportada. Essa restrição se aplica a DLLs, mas não a bibliotecas estáticas. Se as suas classes forem no estilo de dados simples, você não deve encontrar este problema.

Para obter links para obter mais informações sobre DLLs, consulte Criar DLLs C/C++ no Visual Studio. Para obter mais informações sobre vinculação implícita e vinculação explícita, consulte Determinar qual método de vinculação usar. Para obter informações sobre como criar DLLs C++ para uso com linguagens de programação que usam convenções de vinculação de linguagem C, consulte Exportando funções C++ para uso em executáveis de linguagem C. Para obter informações sobre como criar DLLs para uso com linguagens .NET, consulte Chamando funções DLL de aplicativos Visual Basic.

Pré-requisitos

  • Microsoft Windows 7 ou posterior. Recomendamos a versão mais recente do Windows para a melhor experiência de desenvolvimento.
  • Visual Studio. Para saber como baixar e instalar o Visual Studio, consulte Instalar o Visual Studio. Ao executar o instalador, certifique-se de que o desenvolvimento de ambiente de trabalho com C++ esteja selecionado. Não se preocupe se você não instalou essa carga de trabalho quando instalou o Visual Studio. Você pode executar o instalador novamente e instalá-lo agora.

    Captura de ecrã do Visual Studio Installer, desenvolvimento para ambiente de trabalho com conjunto de funções C++.

  • Visual Studio. Para obter informações sobre como baixar e instalar o Visual Studio 2015, consulte Instalar o Visual Studio 2015. Use uma instalação personalizada para instalar o compilador C++ e as ferramentas, já que elas não são instaladas por padrão.
  • Uma compreensão dos conceitos básicos do uso do IDE do Visual Studio. Se já utilizou aplicações de ambiente de trabalho do Windows antes, provavelmente consegue manter-se atualizado. Para obter uma introdução, consulte Tour de recursos do IDE do Visual Studio.

  • Alguma familiaridade com a linguagem C++. Não se preocupe, não fazemos nada muito complicado.

Observação

Este passo a passo pressupõe que você esteja usando o Visual Studio 2017 versão 15.9 ou posterior. Algumas versões anteriores do Visual Studio 2017 tinham defeitos nos modelos de código ou usavam caixas de diálogo de interface do usuário diferentes. Para evitar problemas, use o instalador do Visual Studio para atualizar o Visual Studio 2017 para a versão 15.9 ou posterior.

Criar o projeto DLL

No conjunto de tarefas a seguir, você cria um projeto para sua DLL, adiciona código e cria-o. Para começar, inicie o IDE do Visual Studio e entre se necessário. As instruções variam um pouco, dependendo de qual versão do Visual Studio você está usando. Para ver as etapas para sua versão preferida do Visual Studio, use o seletor de versão localizado na parte superior do sumário nesta página.

Para criar um projeto DLL no Visual Studio

  1. Na barra de menus, escolha Arquivo>Novo>Projeto para abrir a caixa de diálogo Criar um Novo Projeto .

    Captura de tela da caixa de diálogo Criar um novo projeto com o modelo de biblioteca de vínculo dinâmico realçado.

  2. Na parte superior da caixa de diálogo, defina Language como C++, defina Platform como Windows e defina Project type como Library.

  3. Na lista filtrada de tipos de projeto, selecione Biblioteca de vínculo dinâmico (DLL) e, em seguida, escolha Avançar.

  4. Na página Configurar seu novo projeto , digite MathLibrary na caixa Nome do projeto para especificar um nome para o projeto. Deixe os valores padrão Local e Nome da Solução. Defina Solução para Criar nova solução. Desmarque "Colocar solução e projeto no mesmo diretório" se estiver marcado.

  5. Escolha o botão Criar para criar o projeto.

Quando a solução é criada, você pode ver o projeto gerado e os arquivos de origem na janela Gerenciador de Soluções no Visual Studio.

Captura de tela da janela Gerenciador de Soluções com o projeto MathLibrary realçado.

Para criar um projeto DLL no Visual Studio 2017

  1. Na barra de menus, escolha Arquivo>Novo>Projeto para abrir a caixa de diálogo Novo Projeto .

  2. No painel esquerdo da caixa de diálogo Novo Projeto, selecione Instalado>Visual C++>Windows Desktop. No painel central, selecione Biblioteca de Ligação Dinâmica (DLL). Digite MathLibrary na caixa Nome para especificar um nome para o projeto. Deixe os valores padrão Local e Nome da Solução. Defina Solução para Criar nova solução. Verifique Criar diretório para solução, se estiver desmarcado.

    Captura de ecrã da caixa de diálogo Novo Projeto no Visual Studio 2017 mostrando Biblioteca de Matemática na caixa de texto Nome.

  3. Escolha o botão OK para criar o projeto.

Quando a solução é criada, você pode ver o projeto gerado e os arquivos de origem na janela Gerenciador de Soluções no Visual Studio.

Captura de ecrã da janela Solution Explorer no Visual Studio 2017 com a Biblioteca de Matemática realçada.

Para criar um projeto DLL no Visual Studio 2015 e versões mais antigas

  1. Na barra de menus, escolha Arquivo>Novo>Projeto.

  2. No painel esquerdo da caixa de diálogo Novo Projeto, expanda Modelos Instalados>, selecione Visual C++ e, no painel central, selecione Aplicativo de Console Win32. Digite MathLibrary na caixa de edição Nome para especificar um nome para o projeto. Deixe os valores padrão Local e Nome da Solução. Defina Solução para Criar nova solução. Verifique Criar diretório para solução, se estiver desmarcado.

    Captura de tela da caixa de diálogo Novo Projeto no Visual Studio 2015 mostrando MathLibrary na caixa de texto Nome.

  3. Escolha o botão OK para descartar a caixa de diálogo Novo projeto e iniciar o Assistente de aplicativo Win32.

    Captura de ecrã da página Visão geral do Assistente de aplicação Win32.

  4. Escolha o botão Next . Na página Configurações do aplicativo , em Tipo de aplicativo, selecione DLL.

    Captura de ecrã da página de definições da aplicação Win32 Application Wizard.

  5. Escolha o botão Concluir para criar o projeto.

Quando o assistente concluir a solução, você poderá ver o projeto gerado e os arquivos de origem na janela Gerenciador de Soluções no Visual Studio.

Captura de ecrã da janela Solution Explorer no Visual Studio 2015 com a MathLibrary realçada.

Atualmente, esta DLL não faz muito. Em seguida, você criará um arquivo de cabeçalho para declarar as funções que sua DLL exporta e, em seguida, adicionará as definições de função à DLL para torná-la mais útil.

Para adicionar um arquivo de cabeçalho à DLL

  1. Para criar um arquivo de cabeçalho para suas funções, na barra de menus, escolha Project>Add New Item.

  2. Na caixa de diálogo Adicionar Novo Item , no painel esquerdo, selecione Visual C++. No painel central, selecione Arquivo de cabeçalho (.h). Especifique MathLibrary.h como o nome do arquivo de cabeçalho.

    Captura de tela da caixa de diálogo Adicionar Novo Item com o modelo C mais Arquivo de Cabeçalho selecionado e MathLibrary.h inserido na caixa de texto Nome.

  3. Escolha o botão Adicionar para gerar um arquivo de cabeçalho em branco, que é exibido em uma nova janela do editor.

    Captura de tela do arquivo MathLibrary.h vazio no editor.

  4. Substitua o conteúdo do arquivo de cabeçalho por este código:

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

Este arquivo de cabeçalho declara algumas funções para produzir uma sequência de Fibonacci generalizada, dado dois valores iniciais. Uma chamada para fibonacci_init(1, 1) gere a conhecida sequência numérica de Fibonacci.

Observe as instruções do pré-processador na parte superior do arquivo. O novo modelo de projeto para um projeto DLL adiciona <PROJECTNAME>_EXPORTS às macros de pré-processador definidas. Neste exemplo, o Visual Studio define MATHLIBRARY_EXPORTS quando seu projeto DLL MathLibrary é criado.

Quando a MATHLIBRARY_EXPORTS macro é definida, a MATHLIBRARY_API macro define o __declspec(dllexport) modificador nas declarações de função. Esse modificador diz ao compilador e vinculador para exportar uma função ou variável da DLL para uso por outras aplicações. Quando MATHLIBRARY_EXPORTS é indefinido, por exemplo, quando o arquivo de cabeçalho é incluído por um aplicativo cliente, MATHLIBRARY_API aplica o __declspec(dllimport) modificador às declarações. Esse modificador otimiza a importação da função ou variável em um aplicativo. Para obter mais informações, consulte dllexport, dllimport.

Para adicionar uma implementação à DLL

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no nó Arquivos de Origem e escolha Adicionar>Novo Item. Crie um novo .cpp arquivo chamado MathLibrary.cpp, da mesma forma que você adicionou um novo arquivo de cabeçalho na etapa anterior.

  2. Na janela do editor, selecione a MathLibrary.cpp guia se ela já estiver aberta. Caso contrário, no Gerenciador de Soluções, clique MathLibrary.cpp duas vezes na pasta Arquivos de Origem do projeto MathLibrary para abri-lo.

  3. No editor, substitua o conteúdo do arquivo MathLibrary.cpp pelo seguinte código:

    // 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. Na janela do editor, selecione a guia para MathLibrary.cpp se ela já estiver aberta. Caso contrário, no Gerenciador de Soluções, clique duas vezes em MathLibrary.cpp na pasta Arquivos de código-fonte do projeto MathLibrary para abri-lo.

  2. No editor, substitua o conteúdo do arquivo MathLibrary.cpp pelo seguinte código:

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

Para verificar se tudo funciona até agora, compile a DLL. Para compilar, escolha Build>Build Solution na barra de menus. A DLL e a saída do compilador relacionada são colocadas em uma pasta chamada Debug diretamente abaixo da pasta da solução. Se criar uma compilação de Release, a saída é colocada numa pasta chamada Release. A saída deve ser algo como isto:

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

Parabéns, você criou uma DLL usando o Visual Studio! Em seguida, você criará um aplicativo cliente que usa as funções exportadas pela DLL.

Criar um aplicativo cliente que usa a DLL

Ao criar uma DLL, pense em como os aplicativos cliente podem usá-la. Para chamar as funções ou acessar os dados exportados por uma DLL, o código-fonte do cliente deve ter as declarações disponíveis em tempo de compilação. No momento do link, o vinculador requer informações para resolver as chamadas de função ou acessos a dados. Uma DLL fornece essas informações em uma biblioteca de importação, um arquivo que contém informações sobre como localizar as funções e os dados, em vez do código real. E em tempo de execução, a DLL deve estar disponível para o cliente, em um local que o sistema operacional possa encontrar.

Seja seu próprio ou de terceiros, seu projeto de aplicativo cliente precisa de várias informações para usar uma DLL. Ele precisa encontrar os cabeçalhos que declaram as exportações de DLL, as bibliotecas de importação para o vinculador e a própria DLL. Uma solução é copiar todos esses arquivos para o seu projeto cliente. Para DLLs de terceiros que provavelmente não serão alteradas enquanto o cliente estiver em desenvolvimento, esse método pode ser a melhor maneira de usá-las. No entanto, quando você também cria a DLL, é melhor evitar a duplicação. Se você fizer uma cópia local de arquivos DLL que estão em desenvolvimento, poderá alterar acidentalmente um arquivo de cabeçalho em uma cópia, mas não na outra, ou usar uma biblioteca desatualizada.

Para evitar código fora de sincronização, recomendamos que você defina o caminho de inclusão em seu projeto cliente para incluir os arquivos de cabeçalho DLL diretamente do seu projeto DLL. Além disso, defina o caminho da biblioteca em seu projeto cliente para incluir as bibliotecas de importação de DLL do projeto DLL. E, finalmente, copie a DLL construída do projeto DLL para o diretório de saída da compilação do cliente. Esta etapa permite que seu aplicativo cliente use o mesmo código DLL que você cria.

Para criar um aplicativo cliente no Visual Studio

  1. Na barra de menus, escolha Arquivo>Novo>Projeto para abrir a caixa de diálogo Criar um novo projeto .

  2. Na parte superior da caixa de diálogo, defina Language como C++, defina Platform como Windows e defina Project type como Console.

  3. Na lista filtrada de tipos de projeto, escolha Aplicativo de console e, em seguida, escolha Avançar.

  4. Na página Configurar seu novo projeto , digite MathClient na caixa Nome do projeto para especificar um nome para o projeto. Deixe os valores padrão de Localização e Nome da solução. Defina Solução para Criar nova solução. Desmarque "Colocar solução e projeto no mesmo diretório" se estiver marcado.

    Captura de ecrã da caixa de diálogo Criar um novo projeto com a opção Aplicação da consola realçada.

  5. Escolha o botão Criar para criar o projeto cliente.

Um projeto mínimo de aplicativo de console é criado para você. O nome do arquivo de origem principal é o mesmo que o nome do projeto que você inseriu anteriormente. Neste exemplo, é chamado de MathClient.cpp. Você pode criá-lo, mas ele ainda não usa sua DLL.

Para criar um aplicativo cliente no Visual Studio 2017

  1. Para criar um aplicativo C++ que usa a DLL que você criou, na barra de menus, escolha Arquivo>Novo>Projeto.

  2. No painel esquerdo da caixa de diálogo Novo Projeto, selecione Área de trabalho do Windows em Instalado>Visual C++. No painel central, selecione Aplicativo de Console do Windows. Especifique o nome do projeto, MathClient, na caixa de edição Nome . Deixe os valores Local e Nome da solução como padrão. Defina Solução para Criar nova solução. Se estiver desmarcado, marque Criar diretório para solução.

    Captura de ecrã da caixa de diálogo Novo Projeto com a Aplicação de Consola do Windows realçada e Cliente de Matemática escrito na caixa de texto Nome.

  3. Escolha OK para criar o projeto de aplicativo cliente.

Um projeto mínimo de aplicativo de console é criado para você. O nome do arquivo de origem principal é o mesmo que o nome do projeto que você inseriu anteriormente. Neste exemplo, ele é chamado de MathClient.cpp. Você pode criá-lo, mas ele ainda não usa sua DLL.

Para criar um aplicativo cliente no Visual Studio 2015

  1. Para criar um aplicativo C++ que usa a DLL que você criou, na barra de menus, escolha Arquivo>Novo>Projeto.

  2. No painel esquerdo da caixa de diálogo Novo Projeto, selecione Win32 em Modelos>Instalados>Visual C++. No painel central, selecione Aplicativo de console Win32. Especifique o nome do projeto, MathClient, na caixa de edição Nome . Deixe os valores padrão Local e Nome da Solução. Defina Solução para Criar nova solução. Verifique Criar diretório para solução, se estiver desmarcado.

    Imagem da caixa de diálogo Novo Projeto com a aplicação de consola Win32 Visual C++ realçada e

  3. Escolha o botão OK para descartar a caixa de diálogo Novo projeto e iniciar o Assistente de aplicativo Win32. Na página Visão geral da caixa de diálogo Assistente de aplicativo Win32 , escolha o botão Avançar .

  4. Na página Configurações do aplicativo , em Tipo de aplicativo, selecione Aplicativo de console se ele ainda não estiver selecionado.

  5. Escolha o botão Concluir para criar o projeto.

Quando o assistente de configuração é concluído, é criado para você um projeto mínimo de aplicativo de console. O nome do arquivo de origem principal é o mesmo que o nome do projeto que você inseriu anteriormente. Neste exemplo, ele é chamado de MathClient.cpp. Você pode criá-lo, mas ele ainda não usa sua DLL.

Em seguida, para chamar as funções MathLibrary em seu código-fonte, seu projeto deve incluir o MathLibrary.h arquivo. Você pode copiar esse arquivo de cabeçalho em seu projeto de aplicativo cliente e, em seguida, adicioná-lo ao projeto como um item existente. Este método pode ser uma boa escolha para bibliotecas de terceiros. No entanto, se você estiver trabalhando no código para sua DLL e seu cliente ao mesmo tempo, os arquivos de cabeçalho podem ficar fora de sincronia. Para evitar esse problema, defina o caminho Incluir diretórios adicionais em seu projeto para incluir o caminho para o cabeçalho original.

Para adicionar o cabeçalho DLL ao caminho de inclusão

  1. Clique com o botão direito do mouse no nó MathClient no Gerenciador de Soluções para abrir a caixa de diálogo Páginas de Propriedades .

  2. Na caixa suspensa Configuração , selecione Todas as configurações se ainda não estiver selecionada.

  3. No painel esquerdo, selecione Propriedades> de configuraçãoC/C++>General.

  4. No painel de propriedades, selecione o controlo de menu suspenso ao lado da caixa de edição Diretórios de inclusão adicionais e escolha Editar.

    Captura de tela da caixa de diálogo Páginas de propriedades mostrando o comando Editar na lista suspensa da propriedade Diretórios de inclusão adicionais.

  5. Clique duas vezes no painel superior da caixa de diálogo Diretórios de inclusão adicionais para habilitar um controle de edição. Ou escolha o ícone de pasta para criar uma nova entrada.

  6. No campo de edição, especifique o caminho para a localização do arquivo de cabeçalho MathLibrary.h. Você pode escolher o botão de reticências (...) para navegar até a pasta correta.

    Você também pode inserir um caminho relativo dos arquivos de origem do cliente para a pasta que contém os arquivos de cabeçalho DLL. Se você seguiu as instruções para colocar seu projeto cliente em uma solução separada da DLL, o caminho relativo deve ter esta aparência:

    ..\..\MathLibrary\MathLibrary

    Se a DLL e os projetos de cliente estiverem na mesma solução, o caminho relativo poderá ter esta aparência:

    ..\MathLibrary

    Quando a DLL e os projetos cliente estiverem em outras pastas, ajuste o caminho relativo para corresponder. Ou, use o controlador de reticências para procurar a pasta.

    Captura de ecrã da caixa de diálogo Diretórios de Inclusão Adicionais mostrando o caminho relativo para o diretório MathLibrary.

  7. Depois de inserir o caminho para o arquivo de cabeçalho na caixa de diálogo Diretórios de inclusão adicionais , escolha o botão OK . Na caixa de diálogo Páginas de propriedades , escolha o botão OK para salvar as alterações.

Agora você pode incluir o MathLibrary.h arquivo e usar as funções que ele declara em seu aplicativo cliente. Substitua o conteúdo do MathClient.cpp usando este código:

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

Este código pode ser compilado, mas não vinculado. Se você criar o aplicativo cliente agora, a lista de erros mostrará vários LNK2019 erros. Isso ocorre porque seu projeto está faltando algumas informações: você ainda não especificou que seu projeto tem uma dependência da MathLibrary.lib biblioteca. E você não disse ao vinculador como encontrar o MathLibrary.lib arquivo.

Para corrigir esse problema, você pode copiar o arquivo de biblioteca diretamente para seu projeto de aplicativo cliente. O vinculador iria encontrá-lo e usá-lo automaticamente. No entanto, se a biblioteca e o aplicativo cliente estiverem em desenvolvimento, isso pode levar a alterações em uma cópia que não são mostradas na outra. Para evitar esse problema, você pode definir a propriedade Dependências Adicionais para informar ao sistema de compilação que seu projeto depende do MathLibrary.lib. Além disso, você pode definir um caminho de diretórios de biblioteca adicionais em seu projeto para incluir o caminho para a biblioteca original quando você vincular.

Para adicionar a biblioteca de importação de DLL ao seu projeto

  1. Clique com o botão direito do mouse no nó MathClient no Gerenciador de Soluções e escolha Propriedades para abrir a caixa de diálogo Páginas de Propriedades .

  2. Na caixa suspensa Configuração , selecione Todas as configurações se ainda não estiver selecionada. Ele garante que quaisquer alterações de propriedade se apliquem às compilações Debug e Release.

  3. No painel esquerdo, selecione Configuration Properties>Linker>Input. No painel de propriedades, selecione o controle suspenso ao lado da caixa de edição Dependências Adicionais e escolha Editar.

    Captura de tela da caixa de diálogo Páginas de Propriedades em Entrada que mostra o comando Editar na lista pendente da propriedade Dependências Adicionais.

  4. Na caixa de diálogo Dependências Adicionais , adicione MathLibrary.lib à lista no controle de edição superior.

    Captura de tela da caixa de diálogo Dependências Adicionais mostrando o arquivo MathLibrary.lib.

  5. Escolha OK para voltar à caixa de diálogo Páginas de Propriedades .

  6. No painel esquerdo, selecione Configuration Properties>Linker>General. No painel de propriedades, selecione o menu suspenso ao lado da caixa de edição Diretórios de Biblioteca Adicionais e, em seguida, escolha Editar.

    Captura de ecrã da caixa de diálogo Páginas de Propriedades sob a aba Geral que mostra o comando Editar na lista suspensa da propriedade Diretórios de Biblioteca Adicionais.

  7. Clique duas vezes no painel superior da caixa de diálogo Diretórios de Biblioteca Adicionais para habilitar um controle de edição. No controle de edição, especifique o caminho para o local do MathLibrary.lib arquivo. Por padrão, ele está em uma pasta chamada Debug diretamente sob a pasta de solução DLL. Se você criar uma compilação de versão, o arquivo será colocado em uma pasta chamada Release. Você pode usar a $(IntDir) macro para que o vinculador possa encontrar sua DLL, independentemente do tipo de compilação que você criar. Se você seguiu as instruções para colocar seu projeto cliente em uma solução separada do projeto DLL, o caminho relativo deve ter esta aparência:

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

    Se a sua DLL e os projetos do cliente estiverem em outros locais, ajuste o caminho relativo para corresponder.

    Captura de ecrã da caixa de diálogo Diretórios de Biblioteca Adicionais.

  8. Depois de inserir o caminho para o arquivo de biblioteca na caixa de diálogo Diretórios de Biblioteca Adicionais , escolha o botão OK para voltar à caixa de diálogo Páginas de Propriedades . Escolha OK para salvar as alterações de propriedade.

Seu aplicativo cliente agora pode compilar e vincular com êxito, mas ainda não tem tudo o que precisa para ser executado. Quando o sistema operacional carrega seu aplicativo, ele procura a DLL MathLibrary. Se não conseguir encontrar a DLL em determinados diretórios do sistema, no caminho do ambiente ou no diretório do aplicativo local, o carregamento falhará. Dependendo do sistema operacional, você verá uma mensagem de erro como esta:

Captura de ecrã da caixa de diálogo de erro, MathLibrary DLL não encontrada.

Uma maneira de evitar esse problema é copiar a DLL para o diretório que contém o executável do cliente como parte do processo de compilação. Você pode adicionar um evento pós-compilação ao seu projeto, para adicionar um comando que copia a DLL para o diretório de saída da compilação. O comando especificado aqui copia a DLL somente se ela estiver ausente ou tiver sido alterada. Ele usa macros para copiar de e para os locais de depuração ou versão, com base em sua configuração de compilação.

Para copiar a DLL num evento pós-compilação

  1. Clique com o botão direito do mouse no nó MathClient no Gerenciador de Soluções e escolha Propriedades para abrir a caixa de diálogo Páginas de Propriedades .

  2. Na caixa suspensa Configuração , selecione Todas as configurações se ainda não estiver selecionada.

  3. No painel esquerdo, selecione Configuration Properties>Build Events>Post-Build Event.

  4. No painel de propriedades, selecione o controle de edição no campo Linha de comando . Se você seguiu as instruções para colocar seu projeto cliente em uma solução separada do projeto DLL, digite este comando:

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

    Se sua DLL e projetos de cliente estiverem em outros diretórios, altere o caminho relativo para a DLL para corresponder.

    Captura de ecrã da caixa de diálogo de Páginas de Propriedades mostrando a propriedade da linha de comando do evento pós-compilação.

  5. Escolha o botão OK para salvar as alterações nas propriedades do projeto.

Agora seu aplicativo cliente tem tudo o que precisa para criar e executar. Crie o aplicativo escolhendo Build>Build Solution na barra de menus. A janela de saída no Visual Studio deve ter algo como o exemplo a seguir, dependendo da sua versão do 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 ==========

Parabéns, você criou um aplicativo que chama funções em sua DLL. Agora execute seu aplicativo para ver o que ele faz. Na barra de menus, escolha Depurar>Iniciar Sem Depuração. O Visual Studio abre uma janela de comando para o programa ser executado. A última parte da saída deve ter a seguinte aparência:

Captura de ecrã da saída da janela de comandos quando se inicia a aplicação cliente sem debugging.

Pressione qualquer tecla para descartar a janela de comando.

Agora que você criou uma DLL e um aplicativo cliente, você pode experimentar. Tente definir pontos de interrupção no código do aplicativo cliente e execute o aplicativo no depurador. Veja o que acontece quando você entra em uma chamada de biblioteca. Adicione outras funções à biblioteca ou escreva outro aplicativo cliente que use sua DLL.

Ao implantar seu aplicativo, você também deve implantar as DLLs que ele usa. A maneira mais simples de disponibilizar as DLLs que você cria ou que você inclui de terceiros é colocá-las no mesmo diretório do seu aplicativo. É conhecida como implantação local de aplicativo. Para obter mais informações sobre implantação, consulte Implantação no Microsoft C++.

Consulte também