Przewodnik: tworzenie i używanie własnej biblioteki linków dynamicznych (C++)

W tym przewodniku krok po kroku pokazano, jak za pomocą środowiska IDE programu Visual Studio utworzyć własną bibliotekę linków dynamicznych (DLL) napisaną w języku Microsoft C++ (MSVC). Następnie pokazuje, jak używać biblioteki DLL z innej aplikacji języka C++. Biblioteki DLL (nazywane również bibliotekami udostępnionymi w systemach operacyjnych opartych na system UNIX) są jednym z najbardziej przydatnych rodzajów składników systemu Windows. Można ich używać jako sposobu udostępniania kodu i zasobów oraz zmniejszenia rozmiaru aplikacji. Biblioteki DLL mogą nawet ułatwić obsługę i rozszerzanie aplikacji.

W tym przewodniku utworzysz bibliotekę DLL, która implementuje niektóre funkcje matematyczne. Następnie utworzysz aplikację konsolową, która używa funkcji z biblioteki DLL. Zapoznasz się również z wprowadzeniem do niektórych technik programowania i konwencji używanych w bibliotekach DLL systemu Windows.

W tym przewodniku omówiono następujące zadania:

  • Utwórz projekt DLL w programie Visual Studio.

  • Dodaj wyeksportowane funkcje i zmienne do biblioteki DLL.

  • Utwórz projekt aplikacji konsolowej w programie Visual Studio.

  • Użyj funkcji i zmiennych importowanych z biblioteki DLL w aplikacji konsolowej.

  • Uruchom ukończoną aplikację.

Podobnie jak statycznie połączona biblioteka DLL eksportuje zmienne, funkcje i zasoby według nazwy. Aplikacja kliencka importuje nazwy do używania tych zmiennych, funkcji i zasobów. W przeciwieństwie do statycznie połączonej biblioteki system Windows łączy importy w aplikacji z eksportami w bibliotece DLL w czasie ładowania lub w czasie wykonywania, zamiast łączyć je w czasie połączenia. System Windows wymaga dodatkowych informacji, które nie są częścią standardowego modelu kompilacji języka C++, aby nawiązać te połączenia. Kompilator MSVC implementuje niektóre rozszerzenia specyficzne dla firmy Microsoft dla języka C++, aby dostarczyć te dodatkowe informacje. Wyjaśniamy te rozszerzenia podczas pracy.

Ten przewodnik tworzy dwa rozwiązania programu Visual Studio; skompiluje bibliotekę DLL i jedną, która kompiluje aplikację kliencka. Biblioteka DLL używa konwencji wywoływania języka C. Może być wywoływana z aplikacji napisanych w innych językach programowania, o ile platforma, konwencje wywoływania i łączenie konwencji są zgodne. Aplikacja kliencka używa niejawnego łączenia, gdzie system Windows łączy aplikację z biblioteką DLL w czasie ładowania. To łączenie umożliwia aplikacji wywoływanie funkcji dostarczanych przez bibliotekę DLL tak samo jak funkcje w statycznie połączonej bibliotece.

Ten przewodnik nie obejmuje niektórych typowych sytuacji. Kod nie pokazuje użycia bibliotek DLL języka C++ przez inne języki programowania. Nie pokazuje on, jak utworzyć bibliotekę DLL tylko dla zasobów lub jak używać jawnego łączenia do ładowania bibliotek DLL w czasie wykonywania, a nie w czasie ładowania. Masz pewność, że możesz użyć MSVC i programu Visual Studio, aby wykonać wszystkie te czynności.

Mimo że kod biblioteki DLL jest napisany w języku C++, użyliśmy interfejsów w stylu C dla wyeksportowanych funkcji. Istnieją dwa główne przyczyny: najpierw wiele innych języków obsługuje importowanie funkcji w stylu C. Aplikacja kliencka nie musi być napisana w języku C++. Po drugie, pozwala uniknąć niektórych typowych pułapek związanych z wyeksportowanych klas i funkcji składowych. Łatwo jest zdiagnozować błędy podczas eksportowania klas, ponieważ wszystkie elementy, o których mowa w deklaracji klasy, muszą mieć również wyeksportowane wystąpienie. To ograniczenie dotyczy bibliotek DLL, ale nie bibliotek statycznych. Jeśli klasy mają zwykły styl danych, nie należy napotkać tego problemu.

Aby uzyskać linki do dodatkowych informacji na temat bibliotek DLL, zobacz Tworzenie bibliotek DLL języka C/C++ w programie Visual Studio. Aby uzyskać więcej informacji na temat niejawnego łączenia i jawnego łączenia, zobacz Określanie metody łączenia do użycia. Aby uzyskać informacje na temat tworzenia bibliotek DLL języka C++ do użycia z językami programowania korzystającymi z konwencji łączenia języka C, zobacz Eksportowanie funkcji języka C++ do użycia w plikach wykonywalnych języka C. Aby uzyskać informacje o sposobie tworzenia bibliotek DLL do użycia z językami platformy .NET, zobacz Wywoływanie funkcji DLL z poziomu aplikacji Visual Basic.

Wymagania wstępne

  • Komputer z systemem Microsoft Windows 7 lub nowszym. Zalecamy najnowszą wersję systemu Windows w celu uzyskania najlepszego środowiska programistycznego.
  • Kopia programu Visual Studio. Aby uzyskać informacje na temat pobierania i instalowania programu Visual Studio, zobacz Instalowanie programu Visual Studio. Po uruchomieniu instalatora upewnij się, że jest zaznaczone pole Programowanie aplikacji klasycznych z obciążeniem języka C++ . Nie martw się, jeśli nie zainstalowano tego obciążenia podczas instalowania programu Visual Studio. Instalator można uruchomić ponownie i zainstalować go teraz.

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

  • Kopia programu Visual Studio. Aby uzyskać informacje na temat pobierania i instalowania programu Visual Studio 2015, zobacz Instalowanie programu Visual Studio 2015. Użyj instalacji niestandardowej, aby zainstalować kompilator i narzędzia języka C++, ponieważ nie są instalowane domyślnie.
  • Znajomość podstaw korzystania ze środowiska IDE programu Visual Studio. Jeśli wcześniej używasz aplikacji klasycznych systemu Windows, prawdopodobnie możesz nadążyć. Aby zapoznać się z wprowadzeniem, zobacz Przewodnik po funkcji środowiska IDE programu Visual Studio.

  • Zrozumienie wystarczającej ilości podstaw języka C++, które należy wykonać. Nie martw się, nie robimy nic zbyt skomplikowanego.

Uwaga

W tym przewodniku założono, że używasz programu Visual Studio 2017 w wersji 15.9 lub nowszej. Niektóre starsze wersje programu Visual Studio 2017 miały wady w szablonach kodu lub używały różnych okien dialogowych interfejsu użytkownika. Aby uniknąć problemów, użyj Instalator programu Visual Studio, aby zaktualizować program Visual Studio 2017 do wersji 15.9 lub nowszej.

Tworzenie projektu DLL

W tym zestawie zadań utworzysz projekt dla biblioteki DLL, dodaj kod i skompilujesz go. Aby rozpocząć, uruchom środowisko IDE programu Visual Studio i zaloguj się, jeśli chcesz. Instrukcje różnią się nieznacznie w zależności od używanej wersji programu Visual Studio. Upewnij się, że masz wybraną poprawną wersję w kontrolce w lewym górnym rogu tej strony.

Aby utworzyć projekt DLL w programie Visual Studio 2019

  1. Na pasku menu wybierz pozycję Plik>nowy>projekt, aby otworzyć okno dialogowe Tworzenie nowego projektu.

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

  2. W górnej części okna dialogowego ustaw wartość Język na C++, ustaw wartość Platforma na Windows i ustaw wartość Typ projektu na Wartość Biblioteka.

  3. Z filtrowanej listy typów projektów wybierz pozycję Biblioteka łączy dynamicznych (DLL), a następnie wybierz pozycję Dalej.

  4. Na stronie Konfigurowanie nowego projektu wprowadź mathLibrary w polu Nazwa projektu, aby określić nazwę projektu. Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Usuń zaznaczenie pola wyboru Umieść rozwiązanie i projekt w tym samym katalogu , jeśli jest zaznaczone.

  5. Wybierz przycisk Utwórz, aby utworzyć projekt.

Po utworzeniu rozwiązania w oknie Eksplorator rozwiązań w programie Visual Studio zobaczysz wygenerowany projekt i pliki źródłowe.

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

Aby utworzyć projekt DLL w programie Visual Studio 2017

  1. Na pasku menu wybierz pozycję Plik>nowy>projekt, aby otworzyć okno dialogowe Nowy projekt.

  2. W okienku po lewej stronie okna dialogowego Nowy projekt wybierz pozycję Zainstalowano>program Visual C++>Windows Desktop. W środkowym okienku wybierz pozycję Biblioteka linków dynamicznych (DLL). Wprowadź wartość MathLibrary w polu Nazwa , aby określić nazwę projektu. Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Jeśli nie jest zaznaczony, sprawdź pozycję Utwórz katalog dla rozwiązania .

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

  3. Wybierz przycisk OK, aby utworzyć projekt.

Po utworzeniu rozwiązania w oknie Eksplorator rozwiązań w programie Visual Studio zobaczysz wygenerowany projekt i pliki źródłowe.

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

Aby utworzyć projekt DLL w programie Visual Studio 2015 i starszych wersjach

  1. Na pasku menu wybierz pozycję Plik>nowy>projekt.

  2. W lewym okienku okna dialogowego Nowy projekt rozwiń węzeł Zainstalowane>szablony, a następnie wybierz pozycję Visual C++, a następnie w środkowym okienku wybierz pozycję Aplikacja konsolowa Win32. Wprowadź wartość MathLibrary w polu Edycja nazwy , aby określić nazwę projektu. Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Jeśli nie jest zaznaczony, sprawdź pozycję Utwórz katalog dla rozwiązania .

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

  3. Wybierz przycisk OK, aby zamknąć okno dialogowe Nowy projekt i uruchomić Kreatora aplikacji Win32.

    Screenshot of the Win32 Application Wizard Overview page.

  4. Wybierz przycisk Dalej. Na stronie Aplikacja Ustawienia w obszarze Typ aplikacji wybierz pozycję DLL.

    Screenshot of the Win32 Application Wizard Application Settings Page.

  5. Wybierz przycisk Zakończ, aby utworzyć projekt.

Gdy kreator ukończy rozwiązanie, w oknie Eksplorator rozwiązań w programie Visual Studio będzie można zobaczyć wygenerowany projekt i pliki źródłowe.

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

W tej chwili ta biblioteka DLL nie robi zbyt wiele. Następnie utworzysz plik nagłówka w celu zadeklarowania funkcji eksportowanych przez bibliotekę DLL, a następnie dodasz definicje funkcji do biblioteki DLL, aby uczynić ją bardziej przydatną.

Aby dodać plik nagłówka do biblioteki DLL

  1. Aby utworzyć plik nagłówka dla funkcji, na pasku menu wybierz pozycję Project Add New Item (Dodaj nowy element projektu>).

  2. W oknie dialogowym Dodawanie nowego elementu w okienku po lewej stronie wybierz pozycję Visual C++. W środkowym okienku wybierz pozycję Plik nagłówka (.h). Określ mathLibrary.h jako nazwę pliku nagłówka.

    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. Wybierz przycisk Dodaj, aby wygenerować pusty plik nagłówka, który jest wyświetlany w nowym oknie edytora.

    Screenshot of the empty MathLibrary.h file in the editor.

  4. Zastąp zawartość pliku nagłówka następującym kodem:

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

Ten plik nagłówka deklaruje niektóre funkcje w celu utworzenia uogólnionej sekwencji Fibonacciego, biorąc pod uwagę dwie wartości początkowe. Wywołanie w celu fibonacci_init(1, 1) wygenerowania znanej sekwencji numerów Fibonacciego.

Zwróć uwagę na instrukcje preprocesora w górnej części pliku. Nowy szablon projektu dla projektu DLL jest dodany <PROJECTNAME>_EXPORTS do zdefiniowanych makr preprocesora. W tym przykładzie program Visual Studio definiuje MATHLIBRARY_EXPORTS , kiedy projekt MathLibrary DLL został skompilowany.

Po zdefiniowaniu makra MATHLIBRARY_EXPORTSMATHLIBRARY_API makro ustawia __declspec(dllexport) modyfikator deklaracji funkcji. Ten modyfikator nakazuje kompilatorowi i konsolidatorowi wyeksportowanie funkcji lub zmiennej z biblioteki DLL do użycia przez inne aplikacje. Jeśli MATHLIBRARY_EXPORTS na przykład plik nagłówka jest niezdefiniowany przez aplikację kliencką, MATHLIBRARY_API stosuje __declspec(dllimport) modyfikator do deklaracji. Ten modyfikator optymalizuje importowanie funkcji lub zmiennej w aplikacji. Aby uzyskać więcej informacji, zobacz dllexport, dllimport.

Aby dodać implementację do biblioteki DLL

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy węzeł Pliki źródłowe i wybierz polecenie Dodaj>nowy element. Utwórz nowy plik cpp o nazwie MathLibrary.cpp w taki sam sposób, jak dodano nowy plik nagłówka w poprzednim kroku.

  2. W oknie edytora wybierz kartę MathLibrary.cpp , jeśli jest już otwarta. Jeśli tak nie jest, w Eksplorator rozwiązań kliknij dwukrotnie plik MathLibrary.cpp w folderze Pliki źródłowe projektu MathLibrary, aby go otworzyć.

  3. W edytorze zastąp zawartość pliku MathLibrary.cpp następującym kodem:

    // 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. W oknie edytora wybierz kartę MathLibrary.cpp , jeśli jest już otwarta. Jeśli tak nie jest, w Eksplorator rozwiązań kliknij dwukrotnie plik MathLibrary.cpp w folderze Pliki źródłowe projektu MathLibrary, aby go otworzyć.

  2. W edytorze zastąp zawartość pliku MathLibrary.cpp następującym kodem:

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

Aby sprawdzić, czy wszystko działa do tej pory, skompiluj bibliotekę linków dynamicznych. Aby skompilować, wybierz pozycję Kompiluj>rozwiązanie kompilacji na pasku menu. Pliki DLL i powiązane dane wyjściowe kompilatora znajdują się w folderze o nazwie Debuguj bezpośrednio poniżej folderu rozwiązania. Jeśli tworzysz kompilację wydania, dane wyjściowe są umieszczane w folderze o nazwie Release. Dane wyjściowe powinny wyglądać następująco:

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

Gratulacje, utworzono bibliotekę DLL przy użyciu programu Visual Studio! Następnie utworzysz aplikację kliencką korzystającą z funkcji wyeksportowanych przez bibliotekę DLL.

Tworzenie aplikacji klienckiej korzystającej z biblioteki DLL

Podczas tworzenia biblioteki DLL zastanów się, jak aplikacje klienckie mogą z niej korzystać. Aby wywołać funkcje lub uzyskać dostęp do danych wyeksportowanych przez bibliotekę DLL, kod źródłowy klienta musi mieć deklaracje dostępne w czasie kompilacji. W czasie połączenia konsolidator wymaga informacji, aby rozwiązać problemy z wywołaniami funkcji lub dostępem do danych. Biblioteka DLL dostarcza te informacje w bibliotece importu— plik zawierający informacje o sposobach znajdowania funkcji i danych zamiast rzeczywistego kodu. W czasie wykonywania biblioteka DLL musi być dostępna dla klienta w lokalizacji, którą można znaleźć w systemie operacyjnym.

Niezależnie od tego, czy jesteś właścicielem, czy z innej firmy, projekt aplikacji klienckiej potrzebuje kilku informacji, aby korzystać z biblioteki DLL. Musi znaleźć nagłówki, które deklarują eksporty bibliotek DLL, biblioteki importu dla konsolidatora i samą bibliotekę DLL. Jednym z rozwiązań jest skopiowanie wszystkich tych plików do projektu klienta. W przypadku bibliotek DLL innych firm, które są mało prawdopodobne, aby zmienić się podczas opracowywania klienta, ta metoda może być najlepszym sposobem ich użycia. Jednak podczas kompilowania biblioteki DLL lepiej jest unikać duplikowania. Jeśli utworzysz lokalną kopię plików DLL, które są opracowywane, możesz przypadkowo zmienić plik nagłówka w jednej kopii, ale nie innej lub użyć nieaktualnej biblioteki.

Aby uniknąć braku synchronizacji kodu, zalecamy ustawienie ścieżki dołączania w projekcie klienta w celu uwzględnienia plików nagłówków DLL bezpośrednio z projektu DLL. Ponadto ustaw ścieżkę biblioteki w projekcie klienta, aby uwzględnić biblioteki importu bibliotek DLL z projektu DLL. Na koniec skopiuj skompilowany plik DLL z projektu DLL do katalogu wyjściowego kompilacji klienta. Ten krok umożliwia aplikacji klienckiej używanie tego samego kodu DLL, który tworzysz.

Aby utworzyć aplikację kliencką w programie Visual Studio

  1. Na pasku menu wybierz pozycję Plik>nowy>projekt, aby otworzyć okno dialogowe Tworzenie nowego projektu.

  2. W górnej części okna dialogowego ustaw wartość Language na C++, ustaw wartość Platforma na Windows, a następnie ustaw wartość Project type (Typ projektu) na Console (Konsola).

  3. Z filtrowanej listy typów projektów wybierz pozycję Aplikacja konsolowa, a następnie wybierz pozycję Dalej.

  4. Na stronie Konfigurowanie nowego projektu wprowadź wartość MathClient w polu Nazwa projektu, aby określić nazwę projektu. Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Usuń zaznaczenie pola wyboru Umieść rozwiązanie i projekt w tym samym katalogu , jeśli jest zaznaczone.

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

  5. Wybierz przycisk Utwórz, aby utworzyć projekt klienta.

Zostanie utworzony minimalny projekt aplikacji konsolowej. Nazwa głównego pliku źródłowego jest taka sama jak wprowadzona wcześniej nazwa projektu. W tym przykładzie nosi nazwę MathClient.cpp. Można go skompilować, ale jeszcze nie używa biblioteki DLL.

Aby utworzyć aplikację kliencką w programie Visual Studio 2017

  1. Aby utworzyć aplikację języka C++, która używa utworzonej biblioteki DLL, na pasku menu wybierz pozycję Plik>nowy>projekt.

  2. W okienku po lewej stronie okna dialogowego Nowy projekt wybierz pozycję Pulpit systemu Windows w obszarze Zainstalowane visual>C++. W środkowym okienku wybierz pozycję Aplikacja konsolowa systemu Windows. Określ nazwę projektu MathClient w polu Edycja nazwy . Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Jeśli nie jest zaznaczony, sprawdź pozycję Utwórz katalog dla rozwiązania .

    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. Wybierz przycisk OK , aby utworzyć projekt aplikacji klienckiej.

Zostanie utworzony minimalny projekt aplikacji konsolowej. Nazwa głównego pliku źródłowego jest taka sama jak wprowadzona wcześniej nazwa projektu. W tym przykładzie nosi nazwę MathClient.cpp. Można go skompilować, ale jeszcze nie używa biblioteki DLL.

Aby utworzyć aplikację kliencką w programie Visual Studio 2015

  1. Aby utworzyć aplikację języka C++, która używa utworzonej biblioteki DLL, na pasku menu wybierz pozycję Plik>nowy>projekt.

  2. W lewym okienku okna dialogowego Nowy projekt wybierz pozycję Win32 w obszarze Zainstalowane>szablony>Visual C++. W środkowym okienku wybierz pozycję Aplikacja konsolowa Win32. Określ nazwę projektu MathClient w polu Edycja nazwy . Pozostaw wartości domyślne Location (Lokalizacja) i Solution name (Nazwa rozwiązania). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Jeśli nie jest zaznaczony, sprawdź pozycję Utwórz katalog dla rozwiązania .

    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. Wybierz przycisk OK, aby zamknąć okno dialogowe Nowy projekt i uruchomić Kreatora aplikacji Win32. Na stronie Przegląd okna dialogowego Kreator aplikacji Win32 wybierz przycisk Dalej.

  4. Na stronie Aplikacja Ustawienia w obszarze Typ aplikacji wybierz pozycję Aplikacja konsolowa, jeśli nie została jeszcze wybrana.

  5. Wybierz przycisk Zakończ, aby utworzyć projekt.

Po zakończeniu pracy kreatora zostanie utworzony minimalny projekt aplikacji konsolowej. Nazwa głównego pliku źródłowego jest taka sama jak wprowadzona wcześniej nazwa projektu. W tym przykładzie nosi nazwę MathClient.cpp. Można go skompilować, ale jeszcze nie używa biblioteki DLL.

Następnie, aby wywołać funkcje MathLibrary w kodzie źródłowym, projekt musi zawierać plik MathLibrary.h . Możesz skopiować ten plik nagłówkowy do projektu aplikacji klienckiej, a następnie dodać go do projektu jako istniejący element. Ta metoda może być dobrym wyborem dla bibliotek innych firm. Jeśli jednak pracujesz nad kodem biblioteki DLL i klienta w tym samym czasie, pliki nagłówków mogą wyjść z synchronizacji. Aby uniknąć tego problemu, ustaw ścieżkę Dodatkowe katalogi dołączania w projekcie, aby dołączyć ścieżkę do oryginalnego nagłówka.

Aby dodać nagłówek DLL do ścieżki dołączania

  1. Kliknij prawym przyciskiem myszy węzeł MathClient w Eksplorator rozwiązań, aby otworzyć okno dialogowe Strony właściwości.

  2. W polu listy rozwijanej Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana.

  3. W okienku po lewej stronie wybierz pozycję Właściwości>konfiguracji C/C++>General.

  4. W okienku właściwości wybierz kontrolkę listy rozwijanej obok pola edycji Dodatkowe katalogi dołączania, a następnie wybierz pozycję Edytuj.

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

  5. Kliknij dwukrotnie w górnym okienku okna dialogowego Dodatkowe katalogi dołączania, aby włączyć kontrolkę edycji. Możesz też wybrać ikonę folderu, aby utworzyć nowy wpis.

  6. W kontrolce edycji określ ścieżkę do lokalizacji pliku nagłówka MathLibrary.h . Możesz wybrać kontrolkę wielokropka (...), aby przejść do odpowiedniego folderu.

    Możesz również wprowadzić ścieżkę względną z plików źródłowych klienta do folderu zawierającego pliki nagłówka DLL. Jeśli wykonano instrukcje dotyczące umieszczania projektu klienta w osobnym rozwiązaniu niż biblioteka DLL, ścieżka względna powinna wyglądać następująco:

    ..\..\MathLibrary\MathLibrary

    Jeśli biblioteki DLL i projekty klienckie znajdują się w tym samym rozwiązaniu, ścieżka względna może wyglądać następująco:

    ..\MathLibrary

    Gdy biblioteki DLL i projekty klienckie znajdują się w innych folderach, dostosuj ścieżkę względną do dopasowania. Możesz też użyć kontrolki wielokropka, aby wyszukać folder.

    Screenshot of the Additional Include Directories dialog showing the relative path to the MathLibrary directory.

  7. Po wprowadzeniu ścieżki do pliku nagłówka w oknie dialogowym Dodatkowe katalogi dołączania wybierz przycisk OK . W oknie dialogowym Strony właściwości wybierz przycisk OK, aby zapisać zmiany.

Teraz możesz dołączyć plik MathLibrary.h i użyć funkcji zadeklarowanych w aplikacji klienckiej. Zastąp zawartość pliku MathClient.cpp, używając następującego kodu:

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

Ten kod można skompilować, ale nie można połączyć. Jeśli teraz skompilujesz aplikację kliencka, na liście błędów zostanie wyświetlonych kilka błędów LNK2019. Dzieje się tak, ponieważ w projekcie brakuje pewnych informacji: nie określono jeszcze, że projekt ma zależność od biblioteki MathLibrary.lib . I nie powiedziałeś konsolidatorowi, jak znaleźć plik MathLibrary.lib .

Aby rozwiązać ten problem, możesz skopiować plik biblioteki bezpośrednio do projektu aplikacji klienckiej. Konsolidator znajdzie go i użyje go automatycznie. Jeśli jednak zarówno biblioteka, jak i aplikacja kliencka są opracowywane, może to prowadzić do zmian w jednej kopii, która nie jest wyświetlana w drugiej. Aby uniknąć tego problemu , możesz ustawić właściwość Dodatkowe zależności , aby poinformować system kompilacji, że projekt zależy od mathLibrary.lib. Możesz również ustawić ścieżkę Dodatkowych katalogów biblioteki w projekcie, aby dołączyć ścieżkę do oryginalnej biblioteki podczas łączenia.

Aby dodać bibliotekę importowania biblioteki DLL do projektu

  1. Kliknij prawym przyciskiem myszy węzeł MathClient w Eksplorator rozwiązań i wybierz polecenie Właściwości, aby otworzyć okno dialogowe Strony właściwości.

  2. W polu listy rozwijanej Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana. Gwarantuje to, że wszystkie zmiany właściwości mają zastosowanie zarówno do kompilacji debugowania, jak i wydania.

  3. W okienku po lewej stronie wybierz pozycję Właściwości>konfiguracji Wejście konsolidatora.> W okienku właściwości wybierz kontrolkę listy rozwijanej obok pola edycji Dodatkowe zależności , a następnie wybierz pozycję Edytuj.

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

  4. W oknie dialogowym Dodatkowe zależności dodaj bibliotekę MathLibrary.lib do listy w górnej kontrolce edycji.

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

  5. Wybierz przycisk OK , aby wrócić do okna dialogowego Strony właściwości.

  6. W okienku po lewej stronie wybierz pozycję Właściwości>konfiguracji Ogólne konsolidatora.> W okienku właściwości wybierz kontrolkę listy rozwijanej obok pola edycji Dodatkowe katalogi biblioteki, a następnie wybierz pozycję Edytuj.

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

  7. Kliknij dwukrotnie w górnym okienku okna dialogowego Dodatkowe katalogi biblioteki, aby włączyć kontrolkę edycji. W kontrolce edycji określ ścieżkę do lokalizacji pliku MathLibrary.lib . Domyślnie znajduje się on w folderze o nazwie Debuguj bezpośrednio w folderze rozwiązania DLL. Jeśli tworzysz kompilację wydania, plik zostanie umieszczony w folderze o nazwie Release. Możesz użyć makra $(IntDir) , aby konsolidator mógł znaleźć bibliotekę DLL niezależnie od rodzaju tworzonej kompilacji. Jeśli wykonano instrukcje dotyczące umieszczania projektu klienta w osobnym rozwiązaniu niż projekt DLL, ścieżka względna powinna wyglądać następująco:

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

    Jeśli biblioteki DLL i projekty klienckie znajdują się w innych lokalizacjach, dostosuj ścieżkę względną do dopasowania.

    Screenshot of the Additional Library Directories dialog.

  8. Po wprowadzeniu ścieżki do pliku biblioteki w oknie dialogowym Dodatkowe katalogi biblioteki wybierz przycisk OK , aby wrócić do okna dialogowego Strony właściwości. Wybierz przycisk OK , aby zapisać zmiany właściwości.

Aplikacja kliencka może teraz pomyślnie skompilować i połączyć, ale nadal nie ma wszystkiego, czego potrzebuje do uruchomienia. Gdy system operacyjny ładuje aplikację, szuka biblioteki DLL MathLibrary. Jeśli nie można odnaleźć biblioteki DLL w niektórych katalogach systemowych, ścieżce środowiska lub lokalnym katalogu aplikacji, ładowanie zakończy się niepowodzeniem. W zależności od systemu operacyjnego zostanie wyświetlony komunikat o błędzie podobny do następującego:

Screenshot of the error dialog, MathLibrary DLL not found.

Jednym ze sposobów uniknięcia tego problemu jest skopiowanie biblioteki DLL do katalogu zawierającego plik wykonywalny klienta w ramach procesu kompilacji. Do projektu można dodać zdarzenie po kompilacji, aby dodać polecenie, które kopiuje bibliotekę DLL do katalogu wyjściowego kompilacji. Polecenie określone tutaj kopiuje bibliotekę DLL tylko wtedy, gdy jej brakuje lub uległo zmianie. Używa makr do kopiowania do i z lokalizacji debugowania lub wydania na podstawie konfiguracji kompilacji.

Aby skopiować bibliotekę DLL w zdarzeniu po kompilacji

  1. Kliknij prawym przyciskiem myszy węzeł MathClient w Eksplorator rozwiązań i wybierz polecenie Właściwości, aby otworzyć okno dialogowe Strony właściwości.

  2. W polu listy rozwijanej Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana.

  3. W okienku po lewej stronie wybierz pozycję Właściwości>konfiguracji— zdarzenia kompilacji po>kompilacji.

  4. W okienku właściwości wybierz kontrolkę edycji w polu Wiersz polecenia. Jeśli wykonano instrukcje dotyczące umieszczania projektu klienta w osobnym rozwiązaniu niż projekt DLL, wprowadź następujące polecenie:

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

    Jeśli biblioteki DLL i projekty klienckie znajdują się w innych katalogach, zmień ścieżkę względną na bibliotekę DLL tak, aby były zgodne.

    Screenshot of the Property Pages dialog showing the post build event command line property.

  5. Wybierz przycisk OK, aby zapisać zmiany we właściwościach projektu.

Teraz aplikacja kliencka ma wszystko, czego potrzebuje do skompilowania i uruchomienia. Skompiluj aplikację, wybierając pozycję Kompiluj>rozwiązanie kompilacji na pasku menu. Okno Dane wyjściowe w programie Visual Studio powinno wyglądać podobnie do poniższego przykładu w zależności od używanej wersji programu 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 ==========

Gratulacje, utworzono aplikację, która wywołuje funkcje w biblioteki DLL. Teraz uruchom aplikację, aby zobaczyć, co robi. Na pasku menu wybierz pozycję Rozpocznij>bez debugowania. Program Visual Studio otwiera okno polecenia programu do uruchomienia. Ostatnia część danych wyjściowych powinna wyglądać następująco:

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

Naciśnij dowolny klawisz, aby zamknąć okno polecenia.

Po utworzeniu biblioteki DLL i aplikacji klienckiej możesz eksperymentować. Spróbuj ustawić punkty przerwania w kodzie aplikacji klienckiej i uruchomić aplikację w debugerze. Zobacz, co się stanie po wejściu do wywołania biblioteki. Dodaj inne funkcje do biblioteki lub napisz inną aplikację klienczą korzystającą z biblioteki DLL.

Podczas wdrażania aplikacji należy również wdrożyć używane biblioteki DLL. Najprostszym sposobem na utworzenie bibliotek DLL lub dołączenie ich z innych firm jest umieszczenie ich w tym samym katalogu co aplikacja. Jest to nazywane wdrożeniem lokalnym aplikacji. Aby uzyskać więcej informacji na temat wdrażania, zobacz Wdrażanie w języku Visual C++.

Zobacz też

Wywoływanie funkcji DLL z aplikacji języka Visual Basic