Udostępnij za pośrednictwem


Instrukcje: używanie istniejącego kodu C++ w aplikacji platforma uniwersalna systemu Windows

Istnieją różne sposoby używania istniejącego kodu C++ w projektach platformy platforma uniwersalna systemu Windows (UWP). Niektóre sposoby nie wymagają ponownego skompilowania kodu z włączonymi rozszerzeniami składników (C++/CX) (czyli z opcją /ZW ) i niektóre z nich. Może być konieczne zachowanie kodu w standardowym języku C++lub zachowanie klasycznego środowiska kompilacji Win32 dla kodu. Nadal możesz to zrobić przy użyciu odpowiednich opcji architektury. Weź pod uwagę cały kod zawierający interfejs użytkownika platformy UWP i typy, które są widoczne dla obiektów wywołujących języki C#, Visual Basic i JavaScript. Ten kod powinien znajdować się w projektach aplikacji systemu Windows i projektach składników środowisko wykonawcze systemu Windows. Kod wywoływany tylko z języka C++ (w tym C++/CX) może znajdować się w projekcie kompilatora z /ZW opcją lub standardowym projektem C++. Kod tylko binarny, który nie używa niedozwolonych interfejsów API, może być używany przez połączenie go w postaci biblioteki statycznej. Możesz też spakować ją przy użyciu aplikacji jako zawartości i załadować ją do biblioteki DLL.

Być może najprostszym sposobem uruchomienia programu klasycznego w środowisku platformy UWP jest użycie technologii Mostek dla aplikacji klasycznych. Obejmują one konwerter aplikacji klasycznych, który spakuje istniejącą aplikację jako aplikację platformy UNIWERSALNEJ systemu Windows bez konieczności wprowadzania zmian w kodzie. Aby uzyskać więcej informacji, zobacz Mostek dla aplikacji klasycznych.

W pozostałej części tego artykułu omówiono sposób przenoszenia bibliotek języka C++ (bibliotek DLL i bibliotek statycznych) do platforma uniwersalna systemu Windows. Możesz chcieć użyć portu kodu, aby podstawowa logika języka C++ była używana z wieloma aplikacjami platformy UWP.

Aplikacje platformy UWP działają w chronionym środowisku. W związku z tym wiele wywołań interfejsu API Win32, COM i CRT, które mogą naruszyć bezpieczeństwo platformy, nie są dozwolone. Opcja kompilatora /ZW może wykrywać takie wywołania i generować błąd. Możesz użyć zestawu certyfikacji aplikacji w aplikacji, aby wykryć kod, który wywołuje niedozwolone interfejsy API. Aby uzyskać więcej informacji, zobacz Zestaw certyfikacji aplikacji systemu Windows.

Jeśli kod źródłowy jest dostępny dla biblioteki, możesz spróbować wyeliminować niedozwolone wywołania interfejsu API. Aby uzyskać listę interfejsów API, które nie są dozwolone, zobacz Interfejsy API Win32 i COM dla aplikacji platformy UWP i funkcji CRT nieobsługiwane w aplikacjach platforma uniwersalna systemu Windows. Niektóre alternatywy można znaleźć w artykule Alternatywy dla interfejsów API systemu Windows w aplikacjach platformy UWP.

Jeśli po prostu spróbujesz dodać odwołanie z projektu uniwersalnego systemu Windows do klasycznej biblioteki klasycznej, zostanie wyświetlony komunikat o błędzie informujący, że biblioteka nie jest zgodna. Jeśli jest to biblioteka statyczna, możesz połączyć się z biblioteką, dodając bibliotekę (.lib plik) do danych wejściowych konsolidatora, tak samo jak w klasycznej aplikacji Win32. Jeśli dostępna jest tylko biblioteka binarna, jest to jedyna opcja. Biblioteka statyczna jest połączona z plikiem wykonywalnym aplikacji. Jednak biblioteka DLL Win32, której używasz w aplikacji platformy UWP, musi zostać spakowana do aplikacji, dołączając ją do projektu i oznaczając ją jako Zawartość. Aby załadować bibliotekę DLL Win32 w aplikacji platformy UWP, należy również wywołać LoadPackagedLibrary zamiast LoadLibrary lub LoadLibraryEx.

Jeśli masz kod źródłowy biblioteki DLL lub biblioteki statycznej, możesz go ponownie skompilować jako projekt platformy UWP przy użyciu opcji kompilatora /ZW . Następnie możesz dodać do niego odwołanie przy użyciu Eksplorator rozwiązań i użyć go w aplikacjach platformy UWP języka C++. Połącz bibliotekę DLL przy użyciu biblioteki eksportu.

Aby uwidocznić funkcje wywołujących w innych językach, możesz przekonwertować bibliotekę na składnik środowisko wykonawcze systemu Windows. środowisko wykonawcze systemu Windows Składniki różnią się od zwykłych bibliotek DLL, ponieważ zawierają metadane w postaci .winmd plików opisujących zawartość w sposób wymagany przez użytkowników platformy .NET i języka JavaScript. Aby uwidocznić elementy interfejsu API w innych językach, można dodać konstrukcje języka C++/CX, takie jak klasy ref, i upublicznić je. W systemie Windows 10 lub nowszym zalecamy bibliotekę C++/WinRT zamiast C++/CX.

Poprzednia dyskusja nie ma zastosowania do składników COM, które muszą być obsługiwane inaczej. Jeśli masz serwer COM w pliku EXE lub DLL, możesz go użyć w projekcie uniwersalnym systemu Windows. Spakuj go jako składnik COM bez rejestracji, dodaj go do projektu jako plik zawartości i utwórz wystąpienie przy użyciu polecenia CoCreateInstanceFromApp. Aby uzyskać więcej informacji, zobacz Using Free-COM DLL in Windows Store C++ Project (Korzystanie z biblioteki DLL Free-COM w projekcie C++ sklepu Windows Store).

Jeśli chcesz przełączyć istniejącą bibliotekę COM na platformę UWP, można ją również przekonwertować na składnik środowisko wykonawcze systemu Windows. Zalecamy bibliotekę C++/WinRT dla takich portów, ale można również użyć biblioteki szablonów języka C++ (WRL) środowisko wykonawcze systemu Windows. Lista WRL jest przestarzała i nie obsługuje wszystkich funkcji ATL i OLE. To, czy taki port jest możliwy do wykonania, zależy od funkcji modelu COM, ATL i OLE wymaganego składnika.

Niezależnie od wybranego scenariusza programowania należy pamiętać o wielu definicjach makr. Możesz użyć tych makr w kodzie, aby skompilować kod warunkowo w ramach klasycznego pulpitu Win32 i platformy UWP.

#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)

Te instrukcje dotyczą odpowiednio aplikacji platformy UWP, aplikacji ze sklepu Windows Telefon Store, obu lub żadnego z nich (tylko klasyczny system Win32). Te makra są dostępne tylko w zestawie Windows SDK 8.1 lub nowszym.

Ten artykuł zawiera następujące procedury:

Używanie biblioteki DLL Win32 w aplikacji platformy UWP

Aby uzyskać lepsze zabezpieczenia i niezawodność, aplikacje uniwersalne systemu Windows działają w środowisku środowiska uruchomieniowego z ograniczeniami. Nie można po prostu używać żadnej natywnej biblioteki DLL tak, jak w klasycznej aplikacji klasycznej systemu Windows. Jeśli masz kod źródłowy biblioteki DLL, możesz przełączyć kod tak, aby był uruchamiany na platformie UWP. Zacznij od zmiany kilku ustawień projektu i metadanych pliku projektu w celu zidentyfikowania projektu jako projektu platformy UWP. Ponownie skompilujesz kod biblioteki przy użyciu /ZW opcji , która włącza język C++/CX. Niektóre wywołania interfejsu API nie są dozwolone w aplikacjach platformy UWP z powodu bardziej rygorystycznych kontrolek skojarzonych z tym środowiskiem. Aby uzyskać więcej informacji, zobacz Interfejsy API Win32 i COM dla aplikacji platformy UWP.

Jeśli masz natywną bibliotekę DLL, która eksportuje funkcje przy użyciu programu __declspec(dllexport), możesz wywołać te funkcje z aplikacji platformy UWP, ponownie skompilując bibliotekę DLL jako projekt platformy UWP. Załóżmy na przykład, że mamy projekt Dll Win32 o nazwie Giraffe , który eksportuje kilka klas i ich metod z kodem takim jak następujący plik nagłówka:

// giraffe.h
// Define GIRAFFE_EXPORTS when building this DLL
#pragma once

#ifdef GIRAFFE_EXPORTS
#define GIRAFFE_API __declspec(dllexport)
#else
#define GIRAFFE_API
#endif

GIRAFFE_API int giraffeFunction();

class Giraffe
{
    int id;
        Giraffe(int id_in);
    friend class GiraffeFactory;

public:
    GIRAFFE_API int GetID();
};

class GiraffeFactory
{
    static int nextID;

public:
    GIRAFFE_API GiraffeFactory();
    GIRAFFE_API static int GetNextID();
    GIRAFFE_API static Giraffe* Create();
};

I następujący plik kodu:

// giraffe.cpp
#include "pch.h"
#include "giraffe.h"

Giraffe::Giraffe(int id_in) : id(id_in)
{
}

int Giraffe::GetID()
{
    return id;
}

int GiraffeFactory::nextID = 0;

GiraffeFactory::GiraffeFactory()
{
    nextID = 0;
}

int GiraffeFactory::GetNextID()
{
    return nextID;
}

Giraffe* GiraffeFactory::Create()
{
    return new Giraffe(nextID++);
}

int giraffeFunction();

Wszystkie inne elementy w projekcie (pch.h, dllmain.cpp) są częścią standardowego szablonu projektu Win32. Kod definiuje makro GIRAFFE_API, które jest rozpoznawane w __declspec(dllexport) przypadku, gdy GIRAFFE_EXPORTS jest zdefiniowany. Oznacza to, że jest definiowany, gdy projekt jest kompilowany jako biblioteka DLL, ale nie wtedy, gdy klient używa nagłówka giraffe.h . Ta biblioteka DLL może być używana w projekcie platformy UWP bez zmiany kodu źródłowego. Tylko niektóre ustawienia i właściwości projektu muszą ulec zmianie.

Poniższa procedura ma zastosowanie w przypadku natywnej biblioteki DLL, która uwidacznia funkcje przy użyciu polecenia __declspec(dllexport).

Aby przełączyć natywną bibliotekę DLL na platformę UWP bez tworzenia nowego projektu

  1. Otwórz projekt DLL w programie Visual Studio.

  2. Otwórz projekt Właściwości projektu DLL i ustaw wartość Konfiguracja na Wszystkie konfiguracje.

  3. Na karcie Właściwości projektu na karcie C/C++>General (Ogólne) ustaw pozycję Consume środowisko wykonawcze systemu Windows Extension (/ZW) (Korzystanie z rozszerzenia środowisko wykonawcze systemu Windows na Tak (/ZW). Ta właściwość umożliwia rozszerzenia składników (C++/CX).

  4. W Eksplorator rozwiązań wybierz węzeł projektu, otwórz menu skrótów, a następnie wybierz pozycję Zwolnij projekt. Następnie otwórz menu skrótów w węźle zwolnionym projektu i wybierz edycję pliku projektu. WindowsTargetPlatformVersion Znajdź element i zastąp go następującymi elementami.

    <AppContainerApplication>true</AppContainerApplication>
    <ApplicationType>Windows Store</ApplicationType>
    <WindowsTargetPlatformVersion>10.0.10156.0</WindowsTargetPlatformVersion>
    <WindowsTargetPlatformMinVersion>10.0.10156.0</WindowsTargetPlatformMinVersion>
    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
    

    .vcxproj Zamknij plik, otwórz ponownie menu skrótów i wybierz pozycję Załaduj ponownie projekt.

    Eksplorator rozwiązań teraz identyfikuje projekt jako projekt uniwersalny systemu Windows.

  5. Upewnij się, że wstępnie skompilowana nazwa pliku nagłówka jest poprawna. W sekcji Prekompilowane nagłówki może być konieczne zmianę prekompilowanego pliku nagłówka z pch.h na lub w drugą stronę, jeśli zostanie wyświetlony błąd podobny do stdafx.h następującego:

    błąd C2857: instrukcja "#include" określona za pomocą /Ycpch.h opcji wiersza polecenia nie została znaleziona w pliku źródłowym

    Problem polega na tym, że starsze szablony projektów używają innej konwencji nazewnictwa dla wstępnie skompilowanego pliku nagłówka. Program Visual Studio 2019 i nowsze projekty używają programu pch.h.

  6. Skompiluj projekt. Mogą wystąpić błędy dotyczące niezgodnych opcji wiersza polecenia. Na przykład przestarzała, ale często używana opcja Włącz minimalną ponowną kompilację (/Gm) jest domyślnie ustawiona w wielu starszych projektach języka C++ i jest niezgodna z /ZW.

    Niektóre funkcje nie są dostępne podczas kompilowania dla platforma uniwersalna systemu Windows. Zobaczysz błędy kompilatora dotyczące wszelkich problemów. Rozwiąż te błędy, dopóki nie zostanie utworzona czysta kompilacja.

  7. Aby użyć biblioteki DLL w aplikacji platformy UWP w tym samym rozwiązaniu, otwórz menu skrótów dla węzła projektu platformy UWP, a następnie wybierz pozycję Dodaj>odwołanie.

    W obszarze Projekty>Rozwiązanie zaznacz pole wyboru obok projektu DLL i wybierz przycisk OK.

  8. Dołącz pliki nagłówkowe biblioteki do pliku aplikacji platformy pch.h UWP.

    #include "..\Giraffe\giraffe.h"
    
  9. Dodaj kod jak zwykle w projekcie platformy UWP, aby wywoływać funkcje i tworzyć typy z biblioteki DLL.

    MainPage::MainPage()
    {
        InitializeComponent();
        GiraffeFactory gf;
        Giraffe* g = gf.Create();
        int id = g->GetID();
    }
    

Używanie natywnej biblioteki statycznej języka C++ w aplikacji platformy UWP

Możesz użyć natywnej biblioteki statycznej języka C++ w projekcie platformy UWP, ale istnieją pewne ograniczenia i ograniczenia, o których należy pamiętać. Zacznij od przeczytania informacji o bibliotekach statycznych w języku C++/CX. Dostęp do kodu natywnego w bibliotece statycznej można uzyskać z poziomu aplikacji platformy UWP, ale nie zaleca się tworzenia publicznych typów ref w takiej bibliotece statycznej. Jeśli skompilujesz bibliotekę statyczną z opcją /ZW , bibliotekarz (w rzeczywistości konsolidator w ukryciu) wyświetli ostrzeżenie:

LNK4264: archiwizowanie pliku obiektu skompilowanego za pomocą /ZW w bibliotece statycznej; Należy pamiętać, że podczas tworzenia typów środowisko wykonawcze systemu Windows nie zaleca się łączenia z biblioteką statyczną zawierającą metadane środowisko wykonawcze systemu Windows

Można jednak użyć biblioteki statycznej w aplikacji platformy UNIWERSALNEJ systemu Windows bez ponownego komplikowania jej za pomocą polecenia /ZW. Biblioteka nie może zadeklarować żadnych typów ref ani używać konstrukcji C++/CX. Jeśli jednak twoim celem jest użycie biblioteki kodu natywnego, możesz to zrobić, wykonując następujące kroki.

Aby użyć natywnej biblioteki statycznej języka C++ w projekcie platformy UWP

  1. We właściwościach projektu platformy UNIWERSALNEJ systemu Windows wybierz pozycję Właściwości konfiguracji Dane>wejściowe konsolidatora>w okienku po lewej stronie. W okienku po prawej stronie dodaj ścieżkę do biblioteki we właściwości Dodatkowe zależności . Na przykład w przypadku biblioteki w projekcie, która umieszcza jego dane wyjściowe w <SolutionFolder>\Debug\MyNativeLibrary\MyNativeLibrary.libpliku , dodaj ścieżkę Debug\MyNativeLibrary\MyNativeLibrary.libwzględną .

  2. Dodaj instrukcję include, aby odwołać się do pch.h pliku nagłówka (jeśli jest obecny) lub w dowolnym .cpp pliku zgodnie z potrzebami, i rozpocząć dodawanie kodu korzystającego z biblioteki.

    #include "..\MyNativeLibrary\MyNativeLibrary.h"
    

    Nie dodawaj odwołania w węźle Odwołania w Eksplorator rozwiązań. Ten mechanizm działa tylko w przypadku składników środowisko wykonawcze systemu Windows.

Przenoszenie biblioteki C++ do składnika środowisko wykonawcze systemu Windows

Załóżmy, że chcesz korzystać z natywnych interfejsów API w bibliotece statycznej z aplikacji platformy UWP. Jeśli masz kod źródłowy biblioteki natywnej, możesz porcie kodu do składnika środowisko wykonawcze systemu Windows. Nie będzie to już biblioteka statyczna; Przekształcisz ją w bibliotekę DLL, której można użyć w dowolnej aplikacji platformy uniwersalnej systemu Windows w języku C++. W tej procedurze opisano sposób tworzenia nowego składnika środowisko wykonawcze systemu Windows korzystającego z rozszerzeń C++/CX. Aby uzyskać informacje na temat tworzenia składnika korzystającego z języka C++/WinRT, zobacz środowisko wykonawcze systemu Windows składniki z językiem C++/WinRT.

W przypadku korzystania z języka C++/CX można dodawać typy ref i inne konstrukcje C++/CX, które są dostępne dla klientów w dowolnym kodzie aplikacji platformy UWP. Dostęp do tych typów można uzyskać za pomocą języków C#, Visual Basic lub JavaScript. Podstawowa procedura to:

  • Tworzenie projektu składnika środowisko wykonawcze systemu Windows (uniwersalnego systemu Windows),
  • skopiuj do niego kod biblioteki statycznej i
  • rozwiąż wszelkie błędy kompilatora spowodowane przez /ZW tę opcję.

Aby przeportować bibliotekę języka C++ do składnika środowisko wykonawcze systemu Windows

  1. Utwórz projekt środowisko wykonawcze systemu Windows Component (uniwersalny system Windows).

  2. Zamknij projekt.

  3. W Eksplorator plików systemu Windows znajdź nowy projekt. Następnie znajdź projekt biblioteki języka C++, który zawiera kod, który ma zostać port. Skopiuj pliki źródłowe (pliki nagłówkowe, pliki kodu i inne zasoby, w tym w podkatalogach) z projektu biblioteki języka C++. Wklej je do nowego folderu projektu, aby zachować tę samą strukturę folderów.

  4. Otwórz ponownie projekt środowisko wykonawcze systemu Windows Składnik. Otwórz menu skrótów dla węzła projektu w Eksplorator rozwiązań, a następnie wybierz pozycję Dodaj>istniejący element.

  5. Wybierz wszystkie pliki, które chcesz dodać z oryginalnego projektu, a następnie wybierz przycisk OK. Powtórz, jeśli jest to konieczne dla podfolderów.

  6. Być może masz teraz zduplikowany kod. Jeśli istnieje więcej niż jeden wstępnie skompilowany nagłówek (powiedzmy, zarówno, jak stdafx.h i pch.h), wybierz jeden, aby zachować. Skopiuj dowolny wymagany kod, taki jak instrukcje include, do tego, który jest zachowywany. Następnie usuń drugą, a we właściwościach projektu w obszarze Prekompilowane nagłówki upewnij się, że nazwa pliku nagłówka jest poprawna.

    Jeśli plik został zmieniony tak, aby był używany jako prekompilowany nagłówek, upewnij się, że opcje prekompilowanego nagłówka są poprawne dla każdego pliku. Zaznacz każdy .cpp plik z kolei, otwórz okno właściwości i upewnij się, że wszystkie są ustawione na Użyj (/Yu), z wyjątkiem prekompilowanego nagłówka, który powinien być ustawiony na Utwórz (/Yc).

  7. Skompiluj projekt i rozwiąż wszelkie błędy. Te błędy mogą być spowodowane użyciem /ZW opcji lub mogą być spowodowane przez nową wersję zestawu Windows SDK. Mogą też odzwierciedlać zależności, takie jak pliki nagłówkowe, od których zależy biblioteka, lub różnice w ustawieniach projektu między starym projektem a nowym.

  8. Dodaj publiczne typy ref do projektu lub przekonwertuj zwykłe typy na typy ref. Użyj tych typów, aby uwidocznić punkty wejścia w funkcje, które mają być wywoływane z aplikacji platformy UWP.

  9. Przetestuj składnik, dodając do niego odwołanie z projektu aplikacji platformy UWP i dodaj kod w celu wywołania utworzonych publicznych interfejsów API.

Zobacz też

Przenoszenie do platforma uniwersalna systemu Windows