Leggere in inglese

Condividi tramite


Novità di C++/WinRT

Man mano che vengono rilasciate versioni di C++/WinRT successive, questo argomento descrive le novità e le modifiche.

Riepilogo dei miglioramenti o delle aggiunte recenti al mese di marzo 2020

Tempi di compilazione ridotti del 23%

I team di C++/WinRT e del compilatore C++ hanno collaborato per ridurre il più possibile i tempi di compilazione. I dati di analisi del compilatore sono stati esaminati attentamente per comprendere come ristrutturare gli elementi interni di C++/WinRT, in modo da consentire al compilatore C++ di eliminare il sovraccarico in fase di compilazione, e come migliorare il compilatore C++ stesso per gestire la libreria C++/WinRT. C++/WinRT è stato ottimizzato per il compilatore e quest'ultimo è stato ottimizzato per C++/WinRT.

Prendiamo ad esempio lo scenario del caso peggiore in cui viene creata un'intestazione precompilata (PCH) che contiene ogni singola intestazione dello spazio dei nomi della proiezione C++/WinRT.

Versione Dimensione PCH (byte) Ore
C++/WinRT di luglio, con Visual C++ 16.3 3.004.104.632 31
C++/WinRT versione 2.0.200316.3, con Visual C++ 16.5 2.393.515.336 24

Abbiamo ottenuto una riduzione della dimensione del 20% e una riduzione del tempo di compilazione del 23%.

Supporto di MSBuild migliorato

Abbiamo investito molto lavoro per migliorare il supporto di MSBuild per una vasta gamma di scenari diversi.

Memorizzazione nella cache di factory ancora più veloce

Abbiamo migliorato l'inlining della cache di factory per ottenere percorsi critici inline più efficienti, consentendo così un'esecuzione più veloce.

Questo miglioramento non influisce sulle dimensioni del codice, come descritto di seguito in Optimized EH code-gen, se l'applicazione usa molto la gestione delle eccezioni C++, è possibile compattare il file binario usando l'opzione /d2FH4 , che è attivata per impostazione predefinita nei nuovi progetti creati con Visual Studio 2019 16.3 e versioni successive.

Conversione boxing più efficiente

Se usato in un'applicazione XAML, winrt::box_value è ora più efficiente (vedi Boxing e unboxing). Anche per le applicazioni che eseguono molte conversioni boxing potrai notare una riduzione della dimensione del codice.

Supporto per l'implementazione di interfacce COM che implementano IInspectable

È ora possibile implementare un'interfaccia COM (non-Windows-Runtime) che si limita a implementare IInspectable con C++/WinRT. Vedere interfacce COM che implementano IInspectable.

Miglioramenti del blocco dei moduli

Il controllo del blocco dei moduli consente ora sia scenari di hosting personalizzati sia l'eliminazione del blocco a livello di modulo. Vedere Miglioramenti del blocco dei moduli.

Supporto per le informazioni sugli errori di runtime non Windows

Alcune API (anche di Windows Runtime) segnalano errori senza usare API di origine degli errori di Windows Runtime. In casi come questi, C++/WinRT ora ricorre all'uso delle informazioni sugli errori COM. Per informazioni sull'errore non WinRT, vedere Supporto C++/WinRT.

Abilitazione del supporto per i moduli C++

Il supporto per i moduli C++ è di nuovo disponibile, ma solo in via sperimentale. La funzionalità non è ancora completa nel compilatore C++.

Ripresa più efficiente delle coroutine

Le coroutine C++/WinRT funzionano già bene, ma siamo costantemente alla ricerca di soluzioni per migliorarle. Vedere Migliorare la scalabilità della ripresa della coroutine.

Nuovi strumenti asincroni when_all e when_any

La funzione di supporto when_all crea un oggetto IAsyncAction che si completa quando tutti gli oggetti awaitable forniti sono completati. L'helper when_any crea un oggetto IAsyncAction che si completa quando una delle attendibili fornite sono state completate.

Vedi Aggiungi helper asincrono when_any e Aggiungi helper asincrono when_all.

Altre ottimizzazioni e aggiunte

Abbiamo introdotto anche numerose correzioni di bug e ottimizzazioni e aggiunte secondarie, inclusi vari miglioramenti per semplificare il debug e ottimizzare gli elementi interni e le implementazioni predefinite. Segui questo collegamento per un elenco completo: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed.

Funzionalità nuove e aggiornate di C++/WinRT 2.0

Per altre info sul C++/WinRT Visual Studio Extension (VSIX) pacchetto NuGet Microsoft.Windows.CppWinRTe sullo strumento di , incluse le procedure per acquisire e installarle, vedere supporto di Visual Studio per C++/WinRT, XAML, l'estensione VSIX e il pacchetto NuGet.

Modifiche all'estensione di Visual Studio C++/WinRT (VSIX) per la versione 2.0

  • Il visualizzatore di debug supporta ora Visual Studio 2019, oltre a continuare a supportare Visual Studio 2017.
  • Sono state apportate numerose correzioni di bug.

Modifiche al pacchetto NuGet Microsoft.Windows.CppWinRT per la versione 2.0

  • Nel pacchetto NuGet Microsoft.Windows.CppWinRT è ora incluso lo strumento cppwinrt.exe che genera su richiesta intestazioni di proiezione della piattaforma per ogni progetto. Pertanto, lo strumento cppwinrt.exe non dipende più da Windows SDK, anche se viene ancora distribuito con l'SDK per motivi di compatibilità.
  • cppwinrt.exe genera ora le intestazioni di proiezione in ogni cartella intermedia specifica della configurazione o della piattaforma ($IntDir) per consentire la generazione di build parallele.
  • Il supporto per la compilazione in C++/WinRT (props/targets) è ora interamente documentato, offrendo così la possibilità di personalizzare i file di progetto in modo manuale. Vedere il file README del pacchetto NuGet Microsoft.Windows.CppWinRT.
  • Sono state apportate numerose correzioni di bug.

Modifiche a C++/WinRT per la versione 2.0

Open source

Lo cppwinrt.exe strumento accetta un file di metadati (.winmd) di Windows Runtime e genera da esso una libreria C++ standard basata su file di intestazione che proietta le API descritte nei metadati. Puoi così utilizzare tali API dal codice C++/WinRT.

Questo strumento è ora un progetto completamente open source, disponibile su GitHub. Visitare Microsoft/cppwinrt.

Librerie xlang

Una libreria di sole intestazioni completamente portabile (per l'analisi del formato di metadati ECMA-335 usato da Windows Runtime) costituirà la base di tutti gli strumenti di Windows Runtimes e xlang in futuro. In particolare, abbiamo anche riscritto completamente lo strumento cppwinrt.exe usando le librerie xlang. Ciò consentirà di eseguire query sui metadati più accurate, risolvendo alcuni annosi problemi relativi alla proiezione del linguaggio C++/WinRT.

Minori dipendenze

Grazie al lettore di metadati xlang, lo strumento cppwinrt.exe ha meno dipendenze. È quindi molto più flessibile, oltre a essere utilizzabile in diversi scenari, soprattutto in ambienti di compilazione vincolati. In particolare, non dipende più da RoMetadata.dll.   Ecco le dipendenze per cppwinrt.exe 2.0.  

  • ADVAPI32.dll
  • KERNEL32.dll
  • SHLWAPI.dll
  • XmlLite.dll

Tutte queste DLL sono disponibili non solo in Windows 10, ma anche in Windows 7 e Windows Vista. Se lo vuoi, il server di compilazione precedente che esegue Windows 7 può ora eseguire cppwinrt.exe per generare intestazioni C++ per il progetto. Con un po' di lavoro, puoi anche eseguire C++/WinRT in Windows 7, se ti interessa.

Confronta l'elenco sopra riportato con queste dipendenze di cppwinrt.exe 1.0.

  • ADVAPI32.dll
  • SHELL32.dll
  • api-ms-win-core-file-l1-1-0.dll
  • XmlLite.dll
  • api-ms-win-core-libraryloader-l1-2-0.dll
  • api-ms-win-core-processenvironment-l1-1-0.dll
  • RoMetadata.dll
  • SHLWAPI.dll
  • KERNEL32.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-timezone-l1-1-0.dll
  • api-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dll
  • OLEAUT32.dll
  • api-ms-win-core-winrt-error-l1-1-0.dll
  • api-ms-win-core-winrt-error-l1-1-1.dll
  • api-ms-win-core-winrt-l1-1-0.dll
  • api-ms-win-core-winrt-string-l1-1-0.dll
  • api-ms-win-core-synch-l1-1-0.dll
  • api-ms-win-core-threadpool-l1-2-0.dll
  • api-ms-win-core-com-l1-1-0.dll
  • api-ms-win-core-com-l1-1-1.dll
  • api-ms-win-core-synch-l1-2-0.dll

Attributo noexcept di Windows Runtime

Windows Runtime ha un nuovo [noexcept] attributo, che puoi usare per decorare i metodi e le proprietà in MIDL 3.0. La presenza dell'attributo indica agli strumenti di supporto che l'implementazione non genera un'eccezione (né restituisce un errore HRESULT). Ciò consente proiezioni del linguaggio per ottimizzare la generazione di codice, evitando così il sovraccarico per la gestione delle eccezioni necessario per supportare eventuali errori delle chiamate all'interfaccia binaria dell'applicazione (ABI).

C++/WinRT sfrutta questo vantaggio generando implementazioni noexcept C++ di codice per l'utilizzo e la creazione di dati. Se hai metodi o proprietà di API che non generano errori e la dimensione del codice è per te motivo di preoccupazione, puoi prendere in considerazione questo attributo.

Generazione del codice ottimizzata

C++/WinRT genera ora (dietro le quinte) codice sorgente C++ ancora più efficiente, consentendo così al compilatore C++ di generare codice binario il più compatto ed efficiente possibile. Molti dei miglioramenti sono stati pensati per ridurre il costo legato alla gestione delle eccezioni, evitando inutili informazioni di correzione. Nei file binari che usano grandi quantità di codice C++/WinRT si noterà una riduzione delle dimensioni del codice di circa il 4%. Il codice risulta anche più efficiente (e viene eseguito più rapidamente) grazie al numero minore di istruzioni.

Questi miglioramenti si basano su una nuova funzionalità di interoperabilità disponibile per gli sviluppatori. Tutti i tipi C++/WinRT che sono proprietari di risorse includono ora un costruttore per acquisire direttamente la proprietà, evitando l'approccio precedente in due fasi.

ABI::Windows::Foundation::IStringable* raw = ...

IStringable projected(raw, take_ownership_from_abi);

printf("%ls\n", projected.ToString().c_str());

Generazione del codice con gestione delle eccezioni ottimizzata

Questa modifica si integra con il lavoro svolto dal team Microsoft dedicato all'ottimizzazione del codice C++ per ridurre il costo legato alla gestione delle eccezioni. Se nel codice usi una notevole quantità di interfacce binarie di applicazione (ABI), ad esempio COM, puoi osservare che una grande quantità di codice segue questo modello.

int32_t Function() noexcept
{
    try
    {
        // code here constitutes unique value.
    }
    catch (...)
    {
        // code here is always duplicated.
    }
}

Lo stesso C++/WinRT genera questo modello per ogni API implementata. Con migliaia di funzioni API, qualsiasi ottimizzazione può avere un peso rilevante. In passato, l'ottimizzatore non rilevava che i blocchi catch sono tutti identici e quindi duplicava una grande quantità di codice attorno a ogni interfaccia ABI, contribuendo così alla convinzione che l'uso di eccezioni nel codice di sistema ha l'effetto di generare file binari di grandi dimensioni. A partire da Visual Studio 2019, tuttavia, il compilatore C++ comprime tutti i funclet catch e archivia solo quelli univoci. Questo comportamento consente di ottenere un'ulteriore riduzione complessiva del 18% nella dimensione del codice per i file binari che si basano in maniera significativa su questo modello. Non solo il codice di gestione delle eccezioni è ora più efficiente rispetto all'uso di codici restituiti, ma anche il rischio di ottenere file binari più grandi è ormai un ricordo del passato.

Miglioramenti incrementali delle build

Lo strumento cppwinrt.exe confronta ora l'output di un file di codice sorgente o di intestazione generato con il contenuto dei file presenti sul disco e scrive il file solo se è stato effettivamente modificato. Ciò consente di risparmiare molto tempo nelle operazioni di I/O su disco e assicura che i file non vengano considerati "dirty" dal compilatore C++. In questo modo, la ricompilazione viene evitata, o almeno ridotta, in molti casi.

Generazione completa delle interfacce generiche

Grazie al lettore di metadati xlang, C++/WinRT genera ora dai metadati tutte le interfacce con parametri o generiche. Le interfacce come Windows::Foundation::Collections::IVector<T> vengono ora generate dai metadati anziché scritte a mano in winrt/base.h. Di conseguenza, la dimensione di winrt/base.h viene dimezzata e le ottimizzazioni vengono generate direttamente nel codice (un'operazione piuttosto difficile con l'approccio manuale).

Importante

Le interfacce come quelle riportate nell'esempio vengono ora inserite nelle rispettive intestazioni di spazio dei nomi, anziché in winrt/base.h. Pertanto, per usare l'interfaccia, dovrai includere l'intestazione di spazio dei nomi appropriata, se non lo hai già fatto.

Ottimizzazioni dei componenti

Questo aggiornamento introduce il supporto per diverse ottimizzazioni aggiuntive per C++/WinRT che richiedono il consenso esplicito, illustrate nelle sezioni seguenti. Poiché queste ottimizzazioni costituiscono modifiche importanti, per il cui supporto possono essere necessarie alcune piccole modifiche, dovrai attivarle in modo esplicito. In Visual Studio impostare la proprietà Proprietà Comuni del progetto>C++/WinRT>Ottimizzato su . Questa operazione ha come risultato l'aggiunta di <CppWinRTOptimized>true</CppWinRTOptimized> al file del progetto e ha lo stesso effetto dell'impostazione dell'opzione -opt[imize] quando viene richiamato cppwinrt.exe dalla riga di comando.

Nei nuovi progetti (creati a partire da un modello di progetto), -opt viene usato per impostazione predefinita.

Costruzione uniforme e accesso diretto all'implementazione

Queste due ottimizzazioni consentono a un componente di accedere direttamente ai rispettivi tipi di implementazione, anche quando usa solo tipi proiettati. Non è necessario usare make, make_self, né get_self se si vuole semplicemente usare la superficie API pubblica. Le chiamate verranno compilate fino alle chiamate dirette nell'implementazione e anche queste potrebbero essere interamente impostate come inline.

Per altre info ed esempi di codice, vedi Acconsentire esplicitamente alla costruzione uniforme e all'accesso diretto all'implementazione.

Factory con cancellazione di tipi

Questa ottimizzazione consente di evitare le dipendenze #include in module.g.cpp in modo che non sia necessario ripetere la compilazione ogni volta che viene modificata una singola classe di implementazione. Questo ha come risultato un miglioramento delle prestazioni di compilazione.

module.g.cpp più intelligente ed efficiente per progetti di grandi dimensioni con più librerie

Il module.g.cpp file contiene ora anche due helper componibili aggiuntivi, denominati winrt_can_unload_now e winrt_get_activation_factory. Questi helper sono stati ideati per progetti di grandi dimensioni, in cui una DLL è composta da un certo numero di librerie, ciascuna con specifiche classi di runtime. In questo caso, è necessario unire manualmente dllGetActivationFactory e DllCanUnloadNow della DLL. Questi helper semplificano notevolmente questa operazione, evitando errori di origine non corretta. Il flag cppwinrt.exe dello strumento -lib può essere usato anche per assegnare a ogni singola libreria uno specifico preambolo (anziché winrt_xxx) in modo che le funzioni di ogni libreria vengano denominate singolarmente e quindi combinate in modo non ambiguo.

Supporto per coroutine

Il supporto per coroutine è incluso automaticamente. In precedenza, il supporto si trovava in più posizioni, e questo era considerato come troppo limitante. Di conseguenza, temporaneamente per la versione 2.0, era richiesto un file di intestazione winrt/coroutine.h che ora non è più necessario. Poiché le interfacce asincrone di Windows Runtime vengono generate in modo automatico, anziché essere scritte manualmente, si trovano ora winrt/Windows.Foundation.h. Oltre a essere più manutenibile e supportabile, significa che gli helper coroutine, ad esempio resume_foreground, non devono più essere aggiunti alla fine di un'intestazione di un namespace specifico. Possono invece includere più naturalmente le rispettive dipendenze. Ciò consente inoltre resume_foreground di supportare non solo la ripresa in un determinato Windows::UI::Core::CoreDispatcher, ma ora può supportare anche la ripresa in un determinato Windows::System::DispatcherQueue. In precedenza, uno solo dei due poteva essere supportato, poiché la definizione poteva risiedere in un solo spazio dei nomi.

Ecco un esempio del supporto di DispatcherQueue .

...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
    bool queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(queued);

    // This is just to simulate queue failure...
    co_await controller.ShutdownQueueAsync();

    queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(!queued);
}

Gli helper di coroutine sono stati ora aggiornati con [[nodiscard]], migliorandone la facilità d'uso. Se dimentichi (o non ti rendi conto) di dover applicare co_await sugli helper per consentirne il funzionamento, grazie a [[nodiscard]] viene ora generato un avviso del compilatore per segnalare tale errore.

Diagnosi facilitata delle allocazioni stack dirette

Poiché i nomi delle classi proiettate e di implementazione sono (per impostazione predefinita) gli stessi e differiscono solo per lo spazio dei nomi, è possibile confondere l'uno con l'altro e creare accidentalmente un'implementazione nello stack, anziché usare la famiglia di helper make. La diagnosi di casi come questo può non essere facile, poiché l'oggetto potrebbe essere eliminato mentre sono ancora presenti riferimenti in sospeso. Questa diagnosi viene ora eseguita tramite un'asserzione, per le compilazioni di debug. Anche se l'asserzione non rileva l'allocazione dello stack all'interno di una coroutine, è comunque utile per intercettare la maggior parte degli errori di questo tipo.

Per altre info, vedi Diagnosi delle allocazioni dirette.

Helper di acquisizione e delegati variadic migliorati

Questo aggiornamento corregge la limitazione relativa agli helper di acquisizione supportando anche i tipi proiettati. Questo problema si verifica di tanto in tanto con le API di interoperabilità di Windows Runtime, quando restituiscono un tipo proiettato.

Questo aggiornamento aggiunge anche il supporto per get_strong e get_weak durante la creazione di un delegato variadic (non Windows Runtime).

Supporto per la distruzione posticipata e uso sicuro di QI durante la distruzione

Nel distruttore di un oggetto di una classe di runtime non è insolito chiamare un metodo che avvia temporaneamente il conteggio dei riferimenti. Quando il conteggio dei riferimenti restituisce zero, l'oggetto viene distrutto una seconda volta. In un'applicazione XAML potrebbe essere necessario eseguire QueryInterface (QI) in un distruttore, per chiamare un'implementazione di pulizia su o giù nella gerarchia. Tuttavia, il conteggio dei riferimenti dell'oggetto ha già raggiunto lo zero e quindi QI determina un rimbalzo del conteggio dei riferimenti.

Questo aggiornamento permette di evitare che il numero dei riferimenti aumenti di nuovo dopo aver raggiunto lo zero, consentendo comunque a QI di usare eventuali riferimenti temporanei necessari durante la distruzione. Questa routine è inevitabile in determinati controlli e applicazioni XAML e C++/WinRT consente ora di gestirla correttamente.

È possibile rinviare la distruzione fornendo una funzione final_release statica nel tipo di implementazione. L'ultimo puntatore rimasto all'oggetto, sotto forma di std::unique_ptr, viene passato al tuo final_release. Puoi quindi scegliere di spostare la proprietà di tale puntatore in un altro contesto. Puoi chiamare senza alcun rischio un metodo QI sul puntatore senza attivare una doppia distruzione. Ma nel punto in cui l'oggetto viene distrutto la differenza del conteggio dei riferimenti deve essere zero.

Il valore restituito di final_release può essere void, un oggetto operazione asincrona, ad esempio IAsyncAction o winrt::fire_and_forget.

struct Sample : implements<Sample, IStringable>
{
    hstring ToString()
    {
        return L"Sample";
    }

    ~Sample()
    {
        // Called when the unique_ptr below is reset.
    }

    static void final_release(std::unique_ptr<Sample> self) noexcept
    {
        // Move 'self' as needed to delay destruction.
    }
};

Nell'esempio seguente, dopo il rilascio di MainPage (per l'ultima volta), viene chiamato final_release. Tale funzione attende cinque secondi (nel pool di thread) e quindi riprende utilizzando il Dispatcher della pagina (che richiede QI/AddRef/Release per funzionare). Pulisce quindi una risorsa su tale thread dell'interfaccia utente. E infine cancella il unique_ptr, che fa sì che il distruttore MainPage venga effettivamente chiamato. Anche in questo distruttore viene chiamato DataContext, che richiede una QI per IFrameworkElement.

Non è necessario implementare il final_release come coroutine. ma questa soluzione può essere utile e consente di spostare la distruzione in un altro thread, come avviene in questo esempio.

struct MainPage : PageT<MainPage>
{
    MainPage()
    {
    }

    ~MainPage()
    {
        DataContext(nullptr);
    }

    static IAsyncAction final_release(std::unique_ptr<MainPage> self)
    {
        co_await 5s;

        co_await resume_foreground(self->Dispatcher());
        co_await self->resource.CloseAsync();

        // The object is destructed normally at the end of final_release,
        // when the std::unique_ptr<MyClass> destructs. If you want to destruct
        // the object earlier than that, then you can set *self* to `nullptr`.
        self = nullptr;
    }
};

Per altre info, vedi Distruzione posticipata.

Supporto migliorato per l'ereditarietà delle interfacce singole di tipo COM

Come per la programmazione di Windows Runtime, C++/WinRT viene usato anche per creare e utilizzare API solo COM. Questo aggiornamento rende possibile l'implementazione di un server COM in cui è presente una gerarchia di interfacce. Questo non è necessario per Windows Runtime, ma lo è per alcune implementazioni di COM.

Gestione corretta dei parametri out

La gestione dei parametri out può talvolta presentare difficoltà, soprattutto per le matrici di Windows Runtime. Con questo aggiornamento, C++/WinRT è molto più affidabile e resiliente agli errori nella gestione di matrici e parametri out, indipendentemente dal fatto che tali parametri risultino da una proiezione del linguaggio o da uno sviluppatore di COM che sta usando l'interfaccia ABI non elaborata e ha commesso l'errore di non inizializzare le variabili in modo coerente. In entrambi i casi, C++/WinRT gestisce in modo corretto questa situazione, passando i tipi proiettati all'interfaccia ABI (ricordando di rilasciare le risorse) e azzerando o cancellando i parametri che arrivano attraverso l'interfaccia ABI.

Gestione affidabile dei token non validi da parte degli eventi

L'implementazione del winrt::event gestisce con eleganza il caso in cui il metodo remove viene chiamato con un valore di token non valido, ovvero un valore non presente nella matrice.

Distruzione delle variabili locali della coroutine prima della restituzione del risultato

Il metodo tradizionale di implementazione di un tipo coroutine può consentire la distruzione delle variabili locali della coroutine dopo che la coroutine termina/completa (anziché prima della sospensione finale). La ripresa di qualsiasi oggetto waiter viene ora posticipata fino alla sospensione finale, per evitare questo problema e offrire anche altri vantaggi.

Novità e modifiche in Windows SDK versione 10.0.17763.0 (Windows 10, versione 1809)

La tabella seguente contiene novità e modifiche per C++/WinRT in Windows SDK versione 10.0.17763.0 (Windows 10, versione 1809).

Funzionalità nuova o modificata Altre informazioni
Modifica che causa un'interruzione. Per la compilazione, C++/WinRT non dipende da intestazioni di Windows SDK. Vedere Isolamento dai file di intestazione di Windows SDK, di seguito.
Il formato del sistema dei progetti di Visual Studio è stato modificato. Vedi Come ridefinire il progetto C++/WinRT in una versione successiva di Windows SDK, di seguito.
Sono disponibili nuove funzioni e classi di base che consentono di passare un oggetto raccolta a una funzione di Windows Runtime o implementare proprietà e i tipi di raccolta personalizzati. Vedi Raccolte con C++/WinRT.
È possibile usare l'estensione di markup {Binding} con le classi di runtime C++/WinRT. Per altre informazioni ed esempi di codice, vedere la panoramica del data binding .
Il supporto per l'annullamento di una coroutine consente di registrare un callback di annullamento. Per altre info ed esempi di codice, vedi Annullamento di un'operazione asincrona e callback di annullamento.
Quando si crea un delegato che punta a una funzione membro, è possibile stabilire un riferimento forte o debole all'oggetto corrente (anziché al puntatore grezzo this) nel punto in cui è registrato il gestore. Per altre info ed esempi di codice, vedi la sezione Se usi una funzione membro come sotto-delegato nella sezione Accesso sicuro a questo puntatore con un delegato di gestione degli eventi.
Sono stati corretti bug rivelati dalla maggiore conformità di Visual Studio allo standard C++. La toolchain LLVM and Clang viene inoltre sfruttata in modo più efficace per convalidare la conformità agli standard di C++/WinRT. Non incontrerai più il problema descritto in Perché non verrà compilato il mio nuovo progetto? Sto usando Visual Studio 2017 (versione 15.8.0 o successiva) e SDK versione 17134

Altre modifiche

  • Modifica che causa un'interruzione. winrt::get_abi(winrt::hstring const&) restituisce void* ora anziché HSTRING. Puoi usare static_cast<HSTRING>(get_abi(my_hstring)); per ottenere un HSTRING. Vedere Interoperabilità con HSTRING dell'ABI.
  • Modifica che causa un'interruzione. winrt::put_abi(winrt::hstring&) ora restituisce void** anziché HSTRING*. Puoi usare reinterpret_cast<HSTRING*>(put_abi(my_hstring)); per ottenere un HSTRING*. Vedere Interoperabilità con HSTRING dell'ABI.
  • Modifica critica HRESULT è ora proiettato come winrt::hresult. Se è necessario un HRESULT (per eseguire il controllo dei tipi o per supportare i tratti di tipo), è possibile static_castusare winrt::hresult. In caso contrario, winrt::hresult converte in HRESULT, purché tu includa unknwn.h prima di includere eventuali intestazioni C++/WinRT.
  • Modifica che causa un'interruzione. IL GUID viene ora proiettato come winrt::guid. Per le API implementate, è necessario usare winrt::guid per i parametri GUID. In caso contrario, winrt::guid converte in GUID, purché tu includa unknwn.h prima di includere eventuali intestazioni C++/WinRT. Vedere Interoperabilità con lo struct GUID di ABI.
  • Modifica decisiva Il costruttore winrt::handle_type è stato protetto rendendolo esplicito (è ora più difficile scrivere codice non corretto con esso). Se è necessario assegnare un valore di handle non elaborato, chiamare invece la funzione handle_type::attach .
  • Modifica che causa un'interruzione. Le firme di WINRT_CanUnloadNow e WINRT_GetActivationFactory sono state modificate. Queste funzioni non devono più essere dichiarate. In alternativa, includi winrt/base.h (che viene inserito automaticamente se includi file di intestazione di spazi dei nomi Windows C++/WinRT) per aggiungere le dichiarazioni di queste funzioni.
  • Per lo struct winrt::clock, from_FILETIME/to_FILETIME sono deprecati a favore di from_file_time/to_file_time.
  • API semplificate che prevedono parametri IBuffer . Quasi tutte le API preferiscono raccolte o matrici. Ma abbiamo sentito che dovremmo semplificare la chiamata di API che si basano su IBuffer. Questo aggiornamento consente l'accesso diretto ai dati dietro un'implementazione di IBuffer . Usa la stessa convenzione di denominazione dei dati usata nei contenitori della libreria standard C++. Tale convenzione evita anche conflitti con i nomi di metadati che iniziano convenzionalmente con una lettera maiuscola.
  • Generazione del codice migliorata. Sono stati introdotti vari miglioramenti per ridurre la dimensione del codice, migliorare l'inlining e ottimizzare la memorizzazione di factory nella cache.
  • Rimozione della ricorsione non necessaria. Quando la riga di comando fa riferimento a una cartella, anziché a uno specifico file .winmd, lo strumento cppwinrt.exe non esegue più la ricerca di file .winmd in modo ricorsivo. Anche lo strumento cppwinrt.exe gestisce ora i duplicati in modo più intelligente ed è più resiliente agli errori degli utenti e agli errori di formato dei file .winmd.
  • Puntatori intelligenti con protezione. In precedenza, i revocatori di evento non riuscivano a eseguire la revoca in caso di assegnazione di un nuovo valore in seguito allo spostamento. Ciò ha contribuito a individuare un problema per cui le classi di smart pointer non gestivano in modo affidabile l'autoassegnazione; derivato dal modello di struct winrt::com_ptr. winrt::com_ptr è stato corretto e i revocatori di eventi sono stati modificati per gestire correttamente le semantiche di movimento in modo che si revochino al momento dell'assegnazione.

Importante

Sono state apportate modifiche importanti alC++/WinRT Visual Studio Extension (VSIX) , sia nella versione 1.0.181002.2 che successivamente nella versione 1.0.190128.4. Per informazioni dettagliate su queste modifiche e su come influiscono sui progetti esistenti, il supporto di Visual Studio per C++/WinRT e versioni precedenti dell'estensione VSIX.

Isolamento dai file di intestazione di Windows SDK

Questa è potenzialmente una modifica rilevante per il tuo codice.

Per la compilazione, C++/WinRT non dipende più da file di intestazione di Windows SDK. I file di intestazione della libreria di runtime C (CRT) e della libreria di modelli standard C++ (STL) non includono intestazioni di Windows SDK. Ciò consente di migliorare la conformità agli standard, evitare dipendenze accidentali e ridurre notevolmente il numero di macro da cui proteggersi.

Questa indipendenza significa che C++/WinRT è ora più flessibile e conforme agli standard e ha maggiori possibilità di diventare un compilatore e una libreria multipiattaforma. Significa inoltre che le intestazioni C++/WinRT non sono soggette a eventuali effettivi negativi delle macro.

Se in precedenza le intestazioni di Windows venivano incluse nel progetto direttamente da C++/WinRT, ora è compito tuo includerle. In ogni caso, è sempre consigliabile includere in modo esplicito le intestazioni da cui si dipende e non lasciare che sia un'altra libreria a includerle.

Attualmente le uniche eccezioni all'isolamento dei file di intestazione di SDK Windows sono rappresentate da valori intrinseci e numerici. Non vi sono problemi noti relativi a queste ultime dipendenze.

Nel tuo progetto puoi riabilitare l'interoperabilità con le intestazioni di Windows SDK, se necessario. È possibile, ad esempio, implementare un'interfaccia COM (rooted in IUnknown). includi unknwn.h prima di qualsiasi intestazione C++/WinRT. In questo modo, la libreria di base di C++/WinRT abilita vari hook per il supporto di interfacce COM classiche. Per un esempio di codice, vedere Creare componenti COM con C++/WinRT. In modo analogo, includi esplicitamente eventuali altre intestazioni di Windows SDK che dichiarano tipi e/o funzioni che vuoi chiamare.

Come impostare una versione più recente di Windows SDK come destinazione per il progetto C++/WinRT

Il metodo per modificare la destinazione di un progetto che ha minori probabilità di causare problemi del compilatore e del linker è anche quello più impegnativo. Questo metodo comporta la creazione di un nuovo progetto (con la versione di Windows SDK selezionata come destinazione) e quindi la copia dei file dal progetto precedente a quello nuovo. Vi saranno sezioni dei tuoi file .vcxproj e .vcxproj.filters precedenti che puoi semplicemente sovrascrivere per evitare di aggiungere file in Visual Studio.

Vi sono tuttavia altri due modi per reimpostare la destinazione di un progetto in Visual Studio.

  • Passare alla proprietà del progetto Versione Generale> diWindows SDK e selezionare Tutte le configurazioni e Tutte le piattaforme. Impostare Versione di Windows SDK sulla versione di destinazione.
  • In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto, scegliere Retarget Projects ,scegliere le versioni di destinazione e quindi fare clic su OK.

Se si verificano errori del compilatore o del linker dopo aver usato uno di questi due metodi, è possibile provare a pulire la soluzione (Compila>soluzione pulita e/o eliminare manualmente tutte le cartelle e i file temporanei) prima di provare a compilare di nuovo.

Se il compilatore C++ genera "error C2039: 'IUnknown': is not a member of ''global namespace''", quindi aggiungi #include <unknwn.h> all'inizio del file pch.h (prima di includere eventuali intestazioni C++/WinRT).

Può anche essere necessario aggiungere #include <hstring.h> dopo tale stringa.

Se il linker C++ genera "error LNK2019: unresolved external symbol _WINRT_CanUnloadNow@0 referenced in function _VSDesignerCanUnloadNow@0", è possibile risolverlo aggiungendo #define _VSDESIGNER_DONT_LOAD_AS_DLL al pch.h file.