Procedura: Usare il codice C++ esistente in un'app piattaforma UWP (Universal Windows Platform)

Esistono diversi modi per usare il codice C++ esistente nei progetti piattaforma UWP (Universal Windows Platform) (UWP). Alcuni modi non richiedono che il codice venga ricompilato con le estensioni del componente (C++/CX) abilitate (vale a dire con l'opzione /ZW ) e alcune operazioni. Potrebbe essere necessario mantenere il codice in C++ standard o mantenere un ambiente di compilazione Win32 classico per un codice. È comunque possibile farlo, con le scelte di architettura appropriate. Prendi in considerazione tutto il codice che contiene l'interfaccia utente e i tipi UWP esposti ai chiamanti C#, Visual Basic e JavaScript. Questo codice deve trovarsi nei progetti app di Windows e nei progetti componente Windows Runtime. Il codice che si chiama solo da C++ (incluso C++/CX) può trovarsi in un progetto che viene compilato con l'opzione /ZW o un progetto C++ standard. Il codice binario che non usa API non consentite può essere usato collegandolo in come libreria statica. In alternativa, è possibile crearne il pacchetto con l'app come contenuto e caricarlo in una DLL.

Il modo più semplice per eseguire il programma desktop nell'ambiente UWP consiste probabilmente nell'usare le tecnologie Desktop Bridge, Includono Desktop App Converter, che consentirà di creare un pacchetto dell'applicazione esistente come app UWP senza apportare modifiche al codice. Per altre informazioni, vedere Desktop Bridge.

Il resto di questo articolo illustra come convertire le librerie C++ (DLL e librerie statiche) nel piattaforma UWP (Universal Windows Platform). Potresti voler convertire il codice in modo che la logica C++ principale possa essere usata con più app UWP.

Le app UWP vengono eseguite in un ambiente protetto. Di conseguenza, molte chiamate API Win32, COM e CRT che potrebbero compromettere la sicurezza della piattaforma non sono consentite. L'opzione /ZW del compilatore può rilevare tali chiamate e generare un errore. È possibile usare il Kit di certificazione app nell'applicazione per rilevare il codice che chiama LE API non consentite. Per altre informazioni vedereKit di certificazione applicazioni Windows.

Se il codice sorgente è disponibile per la libreria, è possibile provare a eliminare le chiamate API non consentite. Per un elenco delle API non consentite, vedi API Win32 e COM per app UWP e funzioni CRT non supportate nelle app piattaforma UWP (Universal Windows Platform). Alcune alternative sono disponibili in Alternatives to Windows APIs in UWP apps (Alternative alle API di Windows nelle app UWP).

Se si tenta di aggiungere un riferimento da un progetto di Windows universale a una libreria desktop classica, viene visualizzato un messaggio di errore che indica che la libreria non è compatibile. Se si tratta di una libreria statica, è possibile collegarsi alla libreria aggiungendo la libreria (.lib file) all'input del linker, allo stesso modo in un'applicazione Win32 classica. Se è disponibile solo una libreria binaria, è l'unica opzione. Una libreria statica è collegata all'eseguibile dell'app. Tuttavia, una DLL Win32 usata in un'app UWP deve essere inserita in un pacchetto nell'app includendola nel progetto e contrassegnandola come Contenuto. Per caricare una DLL Win32 in un'app UWP, devi anche chiamare LoadPackagedLibrary invece di LoadLibrary o LoadLibraryEx.

Se hai codice sorgente per la DLL o la libreria statica, puoi ricompilarla come progetto UWP usando l'opzione del /ZW compilatore. Puoi quindi aggiungere un riferimento a esso usando il Esplora soluzioni e usarlo nelle app UWP C++. Collegare la DLL usando la libreria di esportazione.

Per esporre la funzionalità ai chiamanti in altre lingue, è possibile convertire la libreria in un componente Windows Runtime. I componenti Windows Runtime differiscono dalle NORMALI DLL in quanto includono metadati sotto forma di .winmd file che descrivono il contenuto in modo che i consumer .NET e JavaScript richiedano. Per esporre gli elementi API ad altri linguaggi, è possibile aggiungere costrutti C++/CX, ad esempio classi di riferimento e renderli pubblici. In Windows 10 e versioni successive è consigliabile usare la libreria C++/WinRT anziché C++/CX.

La discussione precedente non si applica ai componenti COM, che devono essere gestiti in modo diverso. Se si dispone di un server COM in un file EXE o DLL, è possibile usarlo in un progetto di Windows universale. Crea il pacchetto come componente COM senza registrazione, aggiungilo al progetto come file di contenuto e crea un'istanza usando CoCreateInstanceFromApp. Per altre informazioni, vedere Using Free-COM DLL in Windows Store C++ Project (Uso di DLL senza COM in progetti C++ di Windows Store).

Se vuoi convertire una libreria COM esistente nella piattaforma UWP, è anche possibile convertirla in un componente Windows Runtime. È consigliabile usare la libreria C++/WinRT per tali porte, ma è anche possibile usare la libreria di modelli C++ di Windows Runtime. WRL è deprecato e non supporta tutte le funzionalità di ATL e OLE. Il fatto che tale porta sia fattibile dipende dalle funzionalità di COM, ATL e OLE richieste dal componente.

A qualsiasi scenario di sviluppo scelto, è necessario tenere presente una serie di definizioni di macro. Puoi usare queste macro nel codice per compilare il codice in modo condizionale sia nel desktop classico Win32 che nella piattaforma 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)

Queste istruzioni rispettivamente si applicano alle app UWP, Windows Phone Store, a entrambe o a nessuna delle due (solo la versione desktop classica Win32). Queste macro sono disponibili solo in Windows SDK 8.1 e versioni successive.

Questo articolo contiene le procedure seguenti:

Uso di una DLL Win32 in un'app UWP

Per una maggiore sicurezza e affidabilità, le app di Windows universali vengono eseguite in un ambiente di runtime con restrizioni. Non è possibile usare solo dll native nel modo in cui si farebbe in un'applicazione desktop di Windows classica. Se si dispone di codice sorgente per una DLL, è possibile trasferire il codice in modo da poterlo utilizzare in UWP. È innanzitutto necessario modificare alcune impostazioni di progetto e i metadati del file di progetto per identificare il progetto come progetto UWP. Si ricompila il codice della libreria usando l'opzione /ZW , che abilita C++/CX. Alcune chiamate API non sono consentite nelle app UWP a causa di controlli più rigorosi associati a tale ambiente. Per altre informazioni, vedi API Win32 e COM per le app UWP.

Se è presente una DLL nativa che consente di esportare funzioni tramite __declspec(dllexport), è possibile chiamare tali funzioni da un'app della piattaforma UWP ricompilando la DLL come progetto della piattaforma UWP. Si supponga, ad esempio, di avere un progetto DLL Win32 denominato Giraffe che esporta un paio di classi e i relativi metodi, con codice simile al file di intestazione seguente:

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

Aggiungere al file il codice seguente:

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

Tutto il resto del progetto (pch.h, dllmain.cpp) fa parte del modello di progetto Win32 standard. Il codice definisce la macro GIRAFFE_API, che viene risolta in __declspec(dllexport) quando GIRAFFE_EXPORTS viene definita. Ovvero, viene definito quando il progetto viene compilato come DLL, ma non quando un client usa l'intestazione giraffe.h . Questa DLL può essere usata in un progetto UWP senza modificare il codice sorgente. È necessario modificare solo alcune impostazioni e proprietà del progetto.

La procedura seguente si applica quando si dispone di una DLL nativa che espone le funzioni usando __declspec(dllexport).

Alla porta di una DLL nativa per UWP senza creare un nuovo progetto

  1. Aprire il progetto DLL in Visual Studio.

  2. Aprire Proprietà progetto per il progetto DLL e impostare Configurazione su Tutte le configurazioni.

  3. In Proprietà progetto della scheda C/C++>Generale impostare Utilizza estensioni di Windows Runtime su Sì (/ZW). Questa proprietà abilita le estensioni dei componenti (C++/CX).

  4. In Esplora soluzioni selezionare il nodo del progetto, aprire il menu di scelta rapida e scegliere Scarica progetto. Quindi, aprire il menu di scelta rapida sul nodo del progetto scaricato e scegliere di modificare il file di progetto. Individuare l'elemento WindowsTargetPlatformVersion e sostituirlo con gli elementi seguenti.

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

    Chiudere il .vcxproj file, aprire di nuovo il menu di scelta rapida e scegliere Ricarica progetto.

    Esplora soluzioni ora identifica il progetto come progetto Windows universale.

  5. Assicurarsi che il nome del file di intestazione precompilato sia corretto. Nella sezione Intestazioni precompilate potrebbe essere necessario modificare il file di intestazione precompilato da pch.h a o in altro modo se viene visualizzato un errore simile al stdafx.h seguente:

    errore C2857: istruzione '#include' specificata con l'opzione della /Ycpch.h riga di comando non trovata nel file di origine

    Il problema è che i modelli di progetto meno recenti usano una convenzione di denominazione diversa per il file di intestazione precompilato. I progetti di Visual Studio 2019 e versioni successive usano pch.h.

  6. Compilare il progetto. Potrebbero verificarsi alcuni errori relativi alle opzioni della riga di comando incompatibili. Ad esempio l'opzione Abilita ricompilazione minima (/Gm), ora deprecata ma usata di frequente, è configurata come impostazione predefinita in molti progetti C++ meno recenti e non è compatibile con /ZW.

    Alcune funzioni non sono disponibili quando si esegue la compilazione per il piattaforma UWP (Universal Windows Platform). Verranno visualizzati errori del compilatore relativi a eventuali problemi. Risolvere questi errori fino a quando non si dispone di una compilazione pulita.

  7. Per usare la DLL in un'app della piattaforma UWP nella stessa soluzione, aprire il menu di scelta rapida per il nodo del progetto della piattaforma UWP e scegliere Aggiungi>Riferimento.

    In Progetti>Soluzione selezionare la casella di controllo accanto al progetto DLL e scegliere il pulsante OK.

  8. Includi i file di intestazione della libreria nel file dell'app pch.h UWP.

    #include "..\Giraffe\giraffe.h"
    
  9. Aggiungere il codice come di consueto nel progetto UWP per richiamare le funzioni e creare tipi dalla DLL.

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

Uso di una libreria statica C++ nativa in un'app UWP

È possibile utilizzare una libreria statica C++ nativa in un progetto UWP, ma esistono alcune restrizioni e limitazioni da tenere presenti. Per prima cosa leggere le informazioni sulle librerie statiche in C++/CX. È possibile accedere al codice nativo nella libreria statica dall'app UWP, ma non è consigliabile creare tipi di riferimento pubblici nelle librerie statiche. Se si compila una libreria statica con l'opzione /ZW, Gestione librerie, in realtà il linker in formato non riconoscibile, invia un avviso:

LNK4264: archiviazione del file oggetto compilato con /ZW in una libreria statica. Quando si creano tipi Windows Runtime, non è consigliabile eseguire il collegamento con una libreria statica che contiene metadati

Tuttavia, puoi usare una libreria statica in un'app UWP senza ricompilarla con /ZW. La libreria non può dichiarare alcun tipo di riferimento o usare costrutti C++/CX. Tuttavia, se lo scopo è usare solo una libreria di codice nativo, è possibile farlo seguendo questa procedura.

Per utilizzare una libreria statica C++ nativa in un progetto UWP

  1. Nelle proprietà di progetto per il progetto UWP, scegliere Proprietà di configurazione>Linker>Input nel riquadro di sinistra. Nel riquadro di destra aggiungere il percorso della libreria nella proprietà Dipendenze aggiuntive. Ad esempio, per una libreria nel progetto che inserisce il relativo output in <SolutionFolder>\Debug\MyNativeLibrary\MyNativeLibrary.lib, aggiungere il percorso Debug\MyNativeLibrary\MyNativeLibrary.librelativo .

  2. Aggiungere un'istruzione include per fare riferimento al pch.h file di intestazione (se presente) o in qualsiasi .cpp file in base alle esigenze e iniziare ad aggiungere codice che usa la libreria.

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

    Non aggiungere un riferimento nel nodo Riferimenti in Esplora soluzioni. Tale meccanismo funziona solo per i componenti Windows Runtime.

Conversione di una libreria C++ in un componente Windows Runtime

Si supponga di voler usare API native in una libreria statica da un'app UWP. Se si dispone del codice sorgente per la libreria nativa, è possibile convertire il codice in un componente Windows Runtime. Non sarà più una libreria statica; lo trasformerai in una DLL che puoi usare in qualsiasi app UWP C++. Questa procedura descrive come creare un nuovo componente Windows Runtime che usa estensioni C++/CX. Per informazioni sulla creazione di un componente che usa invece C++/WinRT, vedi Componenti Windows Runtime con C++/WinRT.

Quando usi C++/CX, puoi aggiungere tipi di riferimento e altri costrutti C++/CX, disponibili per i client in qualsiasi codice dell'app UWP. È possibile accedere a questi tipi da C#, Visual Basic o JavaScript. La procedura di base è la seguente:

  • Creare un progetto di componente Windows Runtime (Windows universale),
  • copiare il codice per la libreria statica in esso e
  • risolvere eventuali errori del compilatore causati dall'opzione /ZW .

Per trasferire una libreria C++ in un componente Windows Runtime

  1. Creare un progetto Windows Runtime Component (Windows universale).

  2. Chiudere il progetto.

  3. In Windows Esplora file individuare il nuovo progetto. Individuare quindi il progetto di libreria C++ che contiene il codice da convertire. Copiare i file di origine (file di intestazione, file di codice e altre risorse, incluse nelle sottodirectory) dal progetto di libreria C++. Incollarli nella nuova cartella del progetto, assicurandosi di mantenere la stessa struttura di cartelle.

  4. Riaprire il progetto componente Windows Runtime. Aprire il menu di scelta rapida per il nodo del progetto in Esplora soluzioni e scegliere Aggiungi>elemento esistente.

  5. Selezionare tutti i file da aggiungere dal progetto originale e scegliere OK. Se necessario, ripetere la procedura per le sottocartelle.

  6. È possibile ora avere codice duplicato. Se sono presenti più intestazioni precompilate (ad esempio, sia stdafx.h che pch.h), scegliere una da mantenere. Copiare il codice necessario, ad esempio le istruzioni include, in quella che si sta mantenendo. Eliminare quindi l'altro e nelle proprietà del progetto, in Intestazioni precompilate, assicurarsi che il nome del file di intestazione sia corretto.

    Se è stato modificato il file da utilizzare come intestazione precompilata, assicurarsi che le opzioni di intestazione precompilata siano corrette per ogni file. Selezionare ogni .cpp file a sua volta, aprire la finestra delle proprietà e assicurarsi che tutti siano impostati su Usa (/Yu), ad eccezione dell'intestazione precompilata, che deve essere impostata su Crea (/Yc).

  7. Compilare il progetto e risolvere eventuali errori. Questi errori potrebbero essere causati dall'uso dell'opzione /ZW oppure potrebbero essere causati da una nuova versione di Windows SDK. In alternativa, potrebbero riflettere dipendenze, ad esempio file di intestazione da cui dipende la libreria o differenze nelle impostazioni del progetto tra il progetto precedente e quello nuovo.

  8. Aggiungere tipi di riferimento pubblici al progetto o convertire i tipi ordinari in tipi ref. Usa questi tipi per esporre i punti di ingresso nella funzionalità che vuoi chiamare dalle app UWP.

  9. Testare il componente aggiungendovi un riferimento da un progetto dell'app UWP e aggiungere codice per chiamare le API pubbliche create.

Vedi anche

Porting to the Universal Windows Platform (Conversione in Universal Windows Platform)