Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym przewodniku krok po kroku wyjaśniono, jak za pomocą środowiska IDE programu Visual Studio utworzyć własną bibliotekę linków dynamicznych (DLL) napisaną w języku Microsoft C++ (MSVC) oraz jak używać biblioteki DLL z innej aplikacji języka C++. Biblioteki DLL, znane również jako biblioteki udostępnione w systemach operacyjnych opartych na systemie UNIX, są jednym z najbardziej przydatnych rodzajów składników systemu Windows. Można ich używać do 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 opisano następujące kroki:
- 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 powiązanej biblioteki, system Windows łączy importy w aplikacji z eksportami w bibliotece DLL podczas ładowania lub działania, zamiast łączyć je w czasie linkowania. 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 na bieżąco.
W tym przewodniku są tworzone dwa rozwiązania programu Visual Studio: jedno, które kompiluje bibliotekę DLL, i jedno, które kompiluje aplikację klienckę. 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, jak utworzyć bibliotekę DLL tylko dla zasobów ani 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żywamy 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 popełniać trudne do zdiagnozowania błędy podczas eksportowania klas, ponieważ wszystkie elementy, o których mowa w deklaracji klasy, muszą mieć również instancje, które są eksportowane. 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. Więcej informacji na temat niejawnego i jawnego łączenia znajdziesz w sekcji 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
- System Microsoft Windows 7 lub nowszy. Zalecamy najnowszą wersję systemu Windows w celu uzyskania najlepszego środowiska programistycznego.
Visual Studio. Aby dowiedzieć się, jak pobrać i zainstalować program Visual Studio, zobacz Instalowanie programu Visual Studio. Po uruchomieniu instalatora upewnij się, że jest zaznaczone pole Programowanie aplikacji komputerowych z językiem C++. Nie martw się, jeśli nie zainstalowałeś tego pakietu funkcji podczas instalowania programu Visual Studio. Instalator można uruchomić ponownie i zainstalować go teraz.
- 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.
Znajomość języka C++. Nie martw się, nie robimy nic zbyt skomplikowanego.
Uwaga / Notatka
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 Instalatora programu Visual Studio, aby zaktualizować program Visual Studio 2017 do wersji 15.9 lub nowszej.
Tworzenie projektu DLL
W poniższym 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. Aby wyświetlić kroki preferowanej wersji programu Visual Studio, użyj selektora wersji znajdującego się w górnej części spisu treści na tej stronie.
Aby utworzyć projekt DLL w programie Visual Studio
Na pasku menu wybierz pozycję >
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.
Z filtrowanej listy typów projektów wybierz pozycję Biblioteka łączy dynamicznych (DLL), a następnie wybierz pozycję Dalej.
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.
Wybierz przycisk Utwórz, aby utworzyć projekt.
Po utworzeniu rozwiązania można zobaczyć wygenerowany projekt i pliki źródłowe w oknie Eksplorator rozwiązań w programie Visual Studio.
Aby utworzyć projekt DLL w programie Visual Studio 2017
Na pasku menu wybierz pozycję >
W okienku po lewej stronie okna dialogowego Nowy projekt wybierz pozycję Zainstalowano>program Visual C++>Windows Desktop. W środkowym okienku wybierz bibliotekę DLL. Wprowadź MathLibrary w polu Nazwa, aby nadać nazwę projektowi. Pozostaw wartości domyślne Location (Lokalizacja ) i Solution name (Nazwa rozwiązania ). Ustaw pozycję Rozwiązanie na utwórz nowe rozwiązanie. Zaznacz opcję Utwórz katalog dla rozwiązania, jeśli nie jest ona zaznaczona.
Wybierz przycisk OK , aby utworzyć projekt.
Po utworzeniu rozwiązania można zobaczyć wygenerowany projekt i pliki źródłowe w oknie Eksplorator rozwiązań w programie Visual Studio.
Aby utworzyć projekt DLL w programie Visual Studio 2015 i starszych wersjach
Na pasku menu wybierz pozycję Plik>>
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ź MathLibrary w polu edycyjnym 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 zaznaczone, zaznacz Utwórz katalog dla rozwiązania.
Wybierz przycisk OK , aby zamknąć okno dialogowe Nowy projekt i uruchomić Kreatora aplikacji Win32.
Wybierz przycisk Dalej. Na stronie Ustawienia aplikacji w obszarze Typ aplikacji wybierz pozycję DLL.
Wybierz przycisk Zakończ , aby utworzyć projekt.
Gdy kreator ukończy rozwiązanie, w oknie Eksplorator rozwiązań w programie Visual Studio zobaczysz wygenerowany projekt i pliki źródłowe.
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
Aby utworzyć plik nagłówka dla funkcji, w menu wybierz Project>Add New Item (Dodaj nowy element).
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.hjako nazwę pliku nagłówka.
Wybierz przycisk Dodaj , aby wygenerować pusty plik nagłówka, który jest wyświetlany w nowym oknie edytora.
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 do fibonacci_init(1, 1) generuje znaną sekwencję liczb Fibonacciego.
Zwróć uwagę na instrukcje preprocesora w górnej części pliku. Nowy szablon projektu dla projektu DLL dodaje <PROJECTNAME>_EXPORTS do zdefiniowanych makr preprocesora. W tym przykładzie program Visual Studio definiuje MATHLIBRARY_EXPORTS , kiedy projekt MathLibrary DLL został skompilowany.
Gdy makro MATHLIBRARY_EXPORTS jest zdefiniowane, makro MATHLIBRARY_API ustawia modyfikator __declspec(dllexport) na deklaracjach funkcji. Ten modyfikator nakazuje kompilatorowi i konsolidatorowi wyeksportowanie funkcji lub zmiennej z biblioteki DLL do użycia przez inne aplikacje. Jeśli MATHLIBRARY_EXPORTS jest niezdefiniowany, na przykład gdy plik nagłówkowy jest dołączany przez aplikację kliencką, MATHLIBRARY_API stosuje modyfikator __declspec(dllimport) 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
W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł Pliki źródłowe i wybierz polecenie Dodaj>nowy element. Utwórz nowy
.cppplik o nazwieMathLibrary.cpp, w taki sam sposób, jak dodano nowy plik nagłówka w poprzednim kroku.W oknie edytora wybierz kartę
MathLibrary.cpp, jeśli jest już otwarta. Jeśli nie, w Eksploratorze rozwiązań kliknijMathLibrary.cppdwukrotnie folder Pliki źródłowe projektu MathLibrary , aby go otworzyć.W edytorze zastąp zawartość
MathLibrary.cpppliku 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_; }
W oknie edytora wybierz kartę MathLibrary.cpp , jeśli jest już otwarta. Jeśli nie, w Eksploratorze rozwiązań kliknij dwukrotnie MathLibrary.cpp w folderze Pliki źródłowe projektu MathLibrary , aby go otworzyć.
W edytorze zastąp zawartość
MathLibrary.cpppliku 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ę DLL. Aby skompilować, wybierz pozycję Kompiluj>rozwiązanie kompilacji na pasku menu. Biblioteka DLL i powiązane dane wyjściowe kompilatora są umieszczane w folderze o nazwie Debug 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ć podobnie do następujących:
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 mogą z niego korzystać aplikacje klienckie. 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. Podczas linkowania linker wymaga informacji do rozwiązania wywołań funkcji lub dostępu 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 biblioteka DLL jest własnością twoją lub zewnętrznej firmy, projekt aplikacji klienckiej potrzebuje kilku informacji, aby z niej korzystać. Musi znaleźć nagłówki, które deklarują eksporty bibliotek DLL, bibliotekę importującą dla linkera oraz samą bibliotekę DLL. Jednym z rozwiązań jest skopiowanie wszystkich tych plików do projektu klienta. W przypadku bibliotek DLL innych firm, które prawdopodobnie nie zmienią się w trakcie opracowywania produktu, ta metoda może być najlepszym sposobem na ich wykorzystanie. 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ę do bibliotek w projekcie klienta, aby uwzględnić biblioteki importu 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
Na pasku menu wybierz pozycję Plik>nowy>projekt , aby otworzyć okno dialogowe Tworzenie nowego projektu .
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).
Z filtrowanej listy typów projektów wybierz pozycję Aplikacja konsolowa, a następnie wybierz pozycję Dalej.
Na stronie Konfigurowanie nowego projektu wprowadź MathClient w polu Nazwa projektu, aby nadać projektowi nazwę. 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.
Wybierz przycisk Utwórz, aby utworzyć projekt klienta.
Minimalny projekt aplikacji konsolowej został utworzony dla Ciebie. 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
Aby utworzyć aplikację języka C++, która używa utworzonej biblioteki DLL, na pasku menu wybierz pozycję Plik>nowy>projekt.
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 zaznaczone, zaznacz Utwórz katalog dla rozwiązania.
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 nazwano to MathClient.cpp. Można go skompilować, ale jeszcze nie używa biblioteki DLL.
Aby utworzyć aplikację kliencką w programie Visual Studio 2015
Aby utworzyć aplikację języka C++, która używa utworzonej biblioteki DLL, na pasku menu wybierz pozycję Plik>nowy>projekt.
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 zaznaczone, zaznacz Utwórz katalog dla rozwiązania.
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 .
Na stronie Ustawienia aplikacji w obszarze Typ aplikacji wybierz pozycję Aplikacja konsolowa , jeśli nie została jeszcze wybrana.
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 jest nazywany 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ć MathLibrary.h plik. 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
Kliknij prawym przyciskiem myszy węzeł MathClient w Eksploratorze rozwiązań , aby otworzyć okno dialogowe Strony właściwości .
W polu listy rozwijanej Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana.
W okienku po lewej stronie wybierz pozycję Właściwości> konfiguracjiC/C++>General.
W okienku właściwości wybierz kontrolkę listy rozwijanej obok pola edycji Dodatkowe katalogi dołączania , a następnie wybierz pozycję Edytuj.
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.
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 postępowałeś zgodnie z instrukcjami dotyczącymi umieszczania projektu klienta w osobnym rozwiązaniu niż biblioteką DLL, ścieżka względna powinna wyglądać następująco:
..\..\MathLibrary\MathLibraryJeśli biblioteki DLL i projekty klienckie znajdują się w tym samym rozwiązaniu, ścieżka względna może wyglądać następująco:
..\MathLibraryGdy biblioteki DLL i projekty klienckie znajdują się w innych folderach, dostosuj ścieżkę względną tak, aby pasowała. Możesz też użyć kontrolki wielokropka, aby wyszukać folder.
Po wpisaniu ścieżki do pliku nagłówka w oknie dialogowym Dodatkowe ścieżki dołączania, kliknij 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 korzystać z funkcji zadeklarowanych w aplikacji klienckiej. Zastąp zawartość obiektu MathClient.cpp przy użyciu tego 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 MathLibrary.lib biblioteki. I nie powiedziałeś linkerowi, jak plik MathLibrary.lib znaleźć.
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. A także, można ustawić ścieżkę Dodatkowych katalogów biblioteki w projekcie, by uwzględnić ścieżkę do oryginalnej biblioteki przy łączeniu.
Aby dodać bibliotekę importowania DLL do projektu
Kliknij prawym przyciskiem myszy węzeł MathClient w Eksploratorze rozwiązań i wybierz polecenie Właściwości , aby otworzyć okno dialogowe Strony właściwości .
W polu listy rozwijanej Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana. Gwarantuje to, że jakiekolwiek zmiany właściwości mają zastosowanie zarówno do debugowania, jak i kompilacji release.
W okienku po lewej stronie wybierz Właściwości konfiguracji>Konsolidator>Wejście. W okienku właściwości wybierz kontrolkę listy rozwijanej obok pola edycji Dodatkowe zależności , a następnie wybierz pozycję Edytuj.
W oknie dialogowym Dodatkowe zależności dodaj
MathLibrary.libdo listy w górnej kontrolce edycji.
Wybierz przycisk OK , aby wrócić do okna dialogowego Strony właściwości .
W okienku po lewej stronie wybierz pozycję Właściwości konfiguracji>Konsolidator>Ogólne. W okienku właściwości wybierz listę rozwijaną obok pola edycji Dodatkowe katalogi biblioteki, a następnie wybierz pozycję Edytuj.
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
MathLibrary.libpliku. 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 linker mógł odnaleźć bibliotekę DLL niezależnie od rodzaju 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.
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:
Jednym ze sposobów uniknięcia tego problemu jest skopiowanie biblioteki DLL do katalogu zawierającego plik wykonywalny klienta w ramach procesu kompilacji. Możesz dodać zdarzenie po kompilacji do projektu, 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 oraz z lokalizacji debugowania albo wydania, zależnie od konfiguracji kompilacji.
Aby skopiować bibliotekę DLL w zdarzeniu po kompilacji
Kliknij prawym przyciskiem myszy węzeł MathClient w Eksploratorze rozwiązań i wybierz polecenie Właściwości , aby otworzyć okno dialogowe Strony właściwości .
W polu rozwijanym Konfiguracja wybierz pozycję Wszystkie konfiguracje , jeśli nie została jeszcze wybrana.
W okienku po lewej stronie wybierz pozycję Właściwości konfiguracji>Zdarzenia kompilacji>.
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ą do biblioteki DLL, aby była odpowiednia.
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 Debugowanie>Uruchom bez debugowania. Visual Studio otwiera okno wiersza poleceń, w którym uruchamiany jest program. Ostatnia część danych wyjściowych powinna wyglądać następująco:
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ę dzieje, gdy zagłębisz się w wywołanie funkcji bibliotecznej. 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 udostępnienia bibliotek DLL, które tworzysz lub dołączasz od 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 Microsoft C++.