Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Als nachfolgende Versionen von C++/WinRT veröffentlicht werden, beschreibt dieses Thema, was neu ist und was geändert wird.
Zusammenfassung der jüngsten Verbesserungen und Ergänzungen, Stand März 2020
Bis zu 23% kürzere Buildzeiten
Die C++/WinRT- und C++-Compilerteams haben zusammen gearbeitet, um alles zu tun, was möglich ist, um Buildzeiten zu verkürzen. Wir haben Compileranalysen eingehend ausgewertet, um herauszufinden, wie die Interna von C++/WinRT umstrukturiert werden können, damit der C++-Compiler Compile-Time-Overhead eliminieren kann, und wie der C++-Compiler selbst verbessert werden kann, um besser mit der C++/WinRT-Bibliothek umgehen zu können. C++/WinRT wurde für den Compiler optimiert; und der Compiler wurde für C++/WinRT optimiert.
Nehmen wir zum Beispiel das Worst-Case-Szenario, bei dem ein vorkompilierter Header (PCH) erstellt wird, der sämtliche Header der C++/WinRT-Projektionsnamespaces enthält.
| Version | PCH-Größe (Bytes) | Zeit (s) |
|---|---|---|
| C++/WinRT ab Juli mit Visual C++ 16.3 | 3,004,104,632 | 31 |
| Version 2.0.200316.3 von C++/WinRT, mit Visual C++ 16.5 | 2,393,515,336 | 24 |
Eine Reduzierung der Größe von 20% und eine Reduzierung der Buildzeit um 23%.
Verbesserte MSBuild-Unterstützung
Wir haben viel Arbeit in die Verbesserung der MSBuild-Unterstützung für eine große Auswahl verschiedener Szenarien investiert.
Noch schnelleres Factory-Caching
Wir haben das Eingliedern des Factorycaches verbessert, um die Inline-Hot-Pfade zu verbessern, was zu einer schnelleren Ausführung führt.
Diese Verbesserung wirkt sich nicht auf die Codegröße aus– wie in optimierter EH-Codegenerierung beschrieben, wenn Ihre Anwendung die C++-Ausnahmebehandlung stark verwendet, können Sie ihre Binärdatei mithilfe der /d2FH4 Option verkleinern, die standardmäßig in neuen Projekten aktiviert ist, die mit Visual Studio 2019 16.3 und höher erstellt wurden.
Effizienteres Boxen
Bei Verwendung in einer XAML-Anwendung ist winrt::box_value jetzt effizienter (siehe Boxen und Unboxing). Anwendungen, die häufig Boxing verwenden, werden ebenfalls eine Reduzierung der Codegröße feststellen.
Unterstützung für die Implementierung von COM-Schnittstellen, die IInspectable implementieren
Wenn Sie eine COM-Schnittstelle (keine Windows-Runtime-) implementieren müssen, die zufällig auch IInspectable implementiert, können Sie dies jetzt mit C++/WinRT tun. Siehe COM-Schnittstellen, die IInspectable implementieren.
Verbesserungen beim Sperren von Modulen
Die Steuerung über die Modulsperrung ermöglicht jetzt sowohl benutzerdefinierte Hostingszenarien als auch die Eliminierung der Sperrung auf Modulebene. Weitere Informationen finden Sie unter Verbesserungen beim Sperren von Modulen.
Unterstützung für Fehlerinformationen, die nicht von der Windows-Runtime stammen
Einige APIs (auch einige Windows-Runtime-APIs) melden Fehler, ohne Windows-Runtime Fehlerursprung-APIs zu verwenden. In solchen Fällen greift C++/WinRT jetzt auf die Verwendung von COM-Fehlerinformationen zurück. Weitere Informationen finden Sie unter C++/WinRT-Unterstützung für Nicht-WinRT-Fehlerinformationen.
Aktivieren der C++-Modulunterstützung
Die C++-Modulunterstützung ist zurück, aber nur in experimenteller Form. Das Feature ist noch nicht im C++-Compiler abgeschlossen.
Effizientere Coroutin-Wiederaufnahme
C++/WinRT Coroutines funktionieren bereits gut, aber wir suchen weiterhin nach Möglichkeiten, dies zu verbessern. Siehe Verbesserung der Skalierbarkeit der Coroutine-Wiederaufnahme.
Neue when_all und when_any asynchrone Hilfsprogramme
Die when_all Hilfsfunktion erstellt ein IAsyncAction-Objekt , das abgeschlossen wird, wenn alle bereitgestellten Awaitables abgeschlossen sind. Die Hilfsfunktion when_any erstellt eine IAsyncAction, die abgeschlossen wird, sobald eines der bereitgestellten Awaitables abgeschlossen ist.
Siehe Hinzufügen von when_any-Async-Hilfsfunktion und Hinzufügen von when_all-Async-Hilfsfunktion.
Weitere Optimierungen und Ergänzungen
Darüber hinaus wurden viele Fehlerbehebungen und kleinere Optimierungen und Ergänzungen eingeführt, einschließlich verschiedener Verbesserungen zur Vereinfachung des Debuggings und zur Optimierung von Internen und Standardimplementierungen. Folgen Sie diesem Link für eine vollständige Liste: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed.
Neuigkeiten und Änderungen in C++/WinRT 2.0
Weitere Informationen zur C++/WinRT-Visual Studio-Erweiterung (VSIX) finden Sie im Microsoft.Windows. CppWinRT NuGet-Paket und das cppwinrt.exe Tool – einschließlich der Informationen zum Erwerben und Installieren – finden Sie unter Visual Studio Unterstützung für C++/WinRT, XAML, die VSIX-Erweiterung und das NuGet-Paket.
Änderungen an der C++/WinRT Visual Studio Extension (VSIX) für Version 2.0
- Der Debug-Visualizer unterstützt jetzt Visual Studio 2019 und weiterhin auch Visual Studio 2017.
- Es wurden zahlreiche Fehlerbehebungen vorgenommen.
Änderungen am Microsoft.Windows. CppWinRT NuGet-Paket für Version 2.0
- Das
cppwinrt.exe-Tool ist jetzt im NuGet-Paket Microsoft.Windows.CppWinRT enthalten, und das Tool generiert bei Bedarf Plattform-Projektionsheader für jedes Projekt. Folglich hängt dascppwinrt.exeTool nicht mehr vom Windows SDK ab (obwohl das Tool aus Kompatibilitätsgründen weiterhin mit dem SDK ausgeliefert wird). -
cppwinrt.exegeneriert jetzt Projektionsheader unter jedem plattform-/konfigurationsspezifischen Zwischenordner ($IntDir), um parallele Builds zu aktivieren. - Die C++/WinRT-Buildunterstützung (Props/Ziele) ist jetzt vollständig dokumentiert, falls Sie Ihre Projektdateien manuell anpassen möchten. Siehe die README des NuGet-Pakets Microsoft.Windows.CppWinRT.
- Es wurden zahlreiche Fehlerbehebungen vorgenommen.
Änderungen an C++/WinRT für Version 2.0
Open Source
Das cppwinrt.exeTool nimmt eine Windows-Runtime-Metadatendatei (.winmd) als Eingabe und generiert daraus eine auf Headerdateien basierende C++-Standardbibliothek, die die in den Metadaten beschriebenen APIs abbildet. Auf diese Weise können Sie diese APIs aus Ihrem C++/WinRT-Code nutzen.
Dieses Tool ist jetzt ein vollständig Open Source Projekt, das auf GitHub verfügbar ist. Besuchen Sie Microsoft/cppwinrt.
xlang-Bibliotheken
Eine vollständig tragbare Header-only-Bibliothek (zum Analysieren des ecMA-335-Metadatenformats, das vom Windows-Runtime verwendet wird) bildet die Grundlage aller Windows-Runtime- und Xlang-Tools in Zukunft. Insbesondere schreiben wir das cppwinrt.exe Tool mit den xlang-Bibliotheken von Grund auf neu. Dies bietet weitaus genauere Metadatenabfragen, um einige langjährige Probleme mit der C++/WinRT-Sprachprojektion zu lösen.
Weniger Abhängigkeiten
Aufgrund des xlang-Metadatenlesers hat das cppwinrt.exe Tool selbst weniger Abhängigkeiten. Dies macht es wesentlich flexibler und kann auch in mehr Szenarien verwendet werden – insbesondere in eingeschränkten Buildumgebungen. Bemerkenswert ist, dass es nicht mehr auf RoMetadata.dll angewiesen ist.
Dies sind die Abhängigkeiten für cppwinrt.exe 2.0.
- ADVAPI32.dll
- KERNEL32.dll
- SHLWAPI.dll
- XmlLite.dll
Alle diese DLLs sind nicht nur auf Windows 10 verfügbar, sondern bis hin zu Windows 7 und sogar Windows Vista. Wenn Sie möchten, kann Ihr alter Buildserver, auf dem Windows 7 läuft, jetzt cppwinrt.exe ausführen, um C++-Header für Ihr Projekt zu generieren. Mit etwas Arbeit können Sie sogar C++/WinRT auf Windows 7 ausführen, wenn Sie dies interessiert.
Kontrastieren Sie die obige Liste mit diesen Abhängigkeiten, die cppwinrt.exe 1.0 hat.
- 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
Das attribut Windows-Runtime noexcept
Die Windows-Runtime verfügt über ein neues [noexcept] Attribut, das Sie verwenden können, um Ihre Methoden und Eigenschaften in MIDL 3.0 zu dekorieren. Das Vorhandensein des Attributs signalisiert unterstützenden Tools, dass Ihre Implementierung keine Ausnahme auslöst und auch kein fehlerhaftes HRESULT zurückgibt. Dadurch können Sprachprojektionen die Codegenerierung optimieren, indem der Ausnahmebehandlungsaufwand vermieden wird, der erforderlich ist, um ABI-Aufrufe (Application Binary Interface) zu unterstützen, die potenziell fehlschlagen können.
C++/WinRT macht sich dies zunutze, indem es C++noexcept-Implementierungen sowohl für den Clientcode als auch für den Implementierungscode erzeugt. Wenn Sie API-Methoden oder -Eigenschaften haben, die nicht fehlschlagen, und Ihnen die Codegröße wichtig ist, können Sie dieses Attribut in Betracht ziehen.
Optimierte Codegenerierung
C++/WinRT generiert jetzt noch effizienteren C++-Quellcode (hinter den Kulissen), sodass der C++-Compiler den kleinsten und effizientesten Binärcode erzeugen kann. Viele der Verbesserungen sind darauf ausgerichtet, die Kosten für die Ausnahmebehandlung zu reduzieren, indem unnötige Entlastungsinformationen vermieden werden. Binärdateien, die große Mengen von C++/WinRT-Code verwenden, sehen ungefähr eine Reduzierung der Codegröße von 4%. Der Code ist auch effizienter (es wird schneller ausgeführt) aufgrund der reduzierten Anweisungsanzahl.
Diese Verbesserungen basieren auch auf einem neuen Interoperabilitätsfeature, das Ihnen zur Verfügung steht. Alle C++/WinRT-Typen, die Ressourcenbesitzer sind, enthalten jetzt einen Konstruktor für die direkte Übernahme des Besitzes, ohne den vorherigen zweistufigen Ansatz zu vermeiden.
ABI::Windows::Foundation::IStringable* raw = ...
IStringable projected(raw, take_ownership_from_abi);
printf("%ls\n", projected.ToString().c_str());
Optimierte Ausnahmebehandlungs-(EH)-Codegenerierung
Diese Änderung ergänzt die Arbeit, die vom Microsoft C++-Optimiererteam durchgeführt wurde, um die Kosten für die Ausnahmebehandlung zu reduzieren. Wenn Sie Anwendungs-Binärschnittstellen (ABIs) (z. B. COM) in Ihrem Code intensiv verwenden, werden Sie feststellen, dass viel Code diesem Muster folgt.
int32_t Function() noexcept
{
try
{
// code here constitutes unique value.
}
catch (...)
{
// code here is always duplicated.
}
}
C++/WinRT selbst generiert dieses Muster für jede implementierte API. Mit Tausenden von API-Funktionen kann jede Optimierung hier signifikant sein. In der Vergangenheit erkannte der Optimierer nicht, dass diese catch-Blöcke alle identisch sind, sodass für jede ABI viel Code dupliziert wurde (was wiederum zu der Annahme beitrug, dass der Einsatz von Ausnahmen im Systemcode zu großen Binärdateien führt). Ab Visual Studio 2019 faltet der C++-Compiler jedoch alle diese Catch-Funclets und speichert nur diejenigen, die einzigartig sind. Das Ergebnis ist eine weitere und insgesamt 18% Reduzierung der Codegröße für Binärdateien, die stark auf dieses Muster angewiesen sind. Nicht nur EH-Code ist jetzt effizienter als die Verwendung von Rückgabecodes, sondern auch die Sorge um größere Binärdateien ist jetzt eine Sache der Vergangenheit.
Inkrementelle Buildverbesserungen
Das cppwinrt.exe Tool vergleicht jetzt die Ausgabe einer generierten Header-/Quelldatei mit dem Inhalt einer vorhandenen Datei auf dem Datenträger und schreibt nur die Datei aus, wenn sich die Datei tatsächlich geändert hat. Dies spart erhebliche Zeit mit Datenträger-E/A und stellt sicher, dass die Dateien vom C++-Compiler nicht als "schmutzig" betrachtet werden. Das Ergebnis ist, dass eine Erneute Kompilierung in vielen Fällen vermieden oder reduziert wird.
Generische Schnittstellen werden jetzt alle generiert.
Aufgrund des xlang-Metadatenlesers generiert C++/WinRT jetzt alle parametrisierten oder generischen Schnittstellen aus Metadaten. Schnittstellen wie Windows::Foundation::Collections::IVector<T> werden jetzt aus Metadaten generiert, anstatt in winrt/base.h von Hand geschrieben zu werden. Das Ergebnis ist, dass die Größe von winrt/base.h halbiert wurde und Optimierungen direkt im Code erzeugt werden (was mit dem manuell entwickelten Ansatz schwierig umzusetzen war).
Important
Schnittstellen wie das angegebene Beispiel werden nun statt in winrt/base.h in ihren jeweiligen Namespace-Headern angezeigt. Wenn Sie dies noch nicht getan haben, müssen Sie also den entsprechenden Namespaceheader einschließen, um die Schnittstelle zu verwenden.
Komponentenoptimierungen
Dieses Update bietet Unterstützung für mehrere zusätzliche Opt-In-Optimierungen für C++/WinRT, die in den folgenden Abschnitten beschrieben werden. Da diese Optimierungen Breaking Changes sind (für deren Unterstützung Sie möglicherweise kleinere Änderungen vornehmen müssen), müssen Sie sie explizit aktivieren. Legen Sie in Visual Studio die Projekteigenschaft "Common Properties>C++/WinRT>" auf "Ja" optimiert fest. Dies bewirkt, dass <CppWinRTOptimized>true</CppWinRTOptimized> zu Ihrer Projektdatei hinzugefügt wird. Und es hat den gleichen Effekt wie das Hinzufügen des -opt[imize] Schalters beim Aufrufen cppwinrt.exe über die Befehlszeile.
Ein neues Projekt (basierend auf einer Projektvorlage) verwendet standardmäßig -opt.
Einheitlicher Aufbau und direkter Zugriff auf die Implementierung
Diese beiden Optimierungen ermöglichen Ihrer Komponente direkten Zugriff auf eigene Implementierungstypen, auch wenn sie nur die projizierten Typen verwenden. Sie müssen weder make, make_self noch get_self verwenden, wenn Sie einfach die öffentliche API-Oberfläche verwenden möchten. Ihre Aufrufe werden kompiliert, um Anrufe in die Implementierung zu leiten, und diese werden möglicherweise sogar vollständig inlineiert.
Weitere Informationen und Codebeispiele finden Sie unter "Opt in to uniform construction" und "Direct Implementation Access".
Typausgelöschte Fabriken
Diese Optimierung vermeidet die #include Abhängigkeiten module.g.cpp , sodass sie nicht jedes Mal neu kompiliert werden muss, wenn sich eine einzelne Implementierungsklasse ändert. Das Ergebnis ist eine verbesserte Build-Performance.
Intelligenter und effizienter module.g.cpp für große Projekte mit mehreren Libs
Die module.g.cpp-Datei enthält nun auch zwei zusätzliche komponierbare Hilfsfunktionen namens winrt_can_unload_now und winrt_get_activation_factory. Diese wurden für größere Projekte entwickelt, bei denen eine DLL aus einer Reihe von Libs besteht, die jeweils über eigene Laufzeitklassen verfügen. In diesem Fall müssen Sie die DllGetActivationFactory- und DllCanUnloadNow-Funktionen der DLL manuell verknüpfen. Diese Hilfsfunktionen erleichtern Ihnen das erheblich, da sie irrtümliche Fehler bei der Ursprungsermittlung vermeiden. Die cppwinrt.exe Kennzeichnung des -lib Tools kann auch verwendet werden, um jeder einzelnen Lib eine eigene Präambel (statt winrt_xxx) zu geben, damit die Funktionen der einzelnen Libs einzeln benannt und somit eindeutig kombiniert werden können.
Coroutine-Unterstützung
Die Unterstützung für Coroutines ist automatisch enthalten. Zuvor war der Support auf mehrere Stellen verteilt, was wir als zu einschränkend empfanden. Und dann war für v2.0 vorübergehend eine winrt/coroutine.h-Headerdatei erforderlich, aber sie wird nicht mehr benötigt. Da die Windows-Runtime asynchronen Schnittstellen jetzt generiert werden und nicht von Hand geschrieben, befinden sie sich jetzt in winrt/Windows.Foundation.h. Abgesehen davon, dass sie besser wartbar und einfacher zu unterstützen ist, bedeutet dies, dass Coroutine-Hilfsfunktionen wie resume_foreground nicht länger an das Ende eines bestimmten Namespace-Headers angehängt werden müssen. Stattdessen können sie ihre Abhängigkeiten auf natürlichere Weise einbinden. Dies ermöglicht resume_foreground außerdem, nicht nur die Fortsetzung für einen angegebenen Windows::UI::Core::CoreDispatcher zu unterstützen, sondern nun auch die Fortsetzung für eine angegebene Windows::System::DispatcherQueue. Bisher konnte nur eins unterstützt werden; aber nicht beides, da sich die Definition nur in einem Namespace befinden konnte.
Hier ist ein Beispiel für die DispatcherQueue-Unterstützung .
...
#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);
}
Die Coroutine-Helfer sind jetzt ebenfalls mit [[nodiscard]] versehen, wodurch ihre Benutzerfreundlichkeit verbessert wird. Wenn Sie vergessen, co_await sie zu verwenden (oder nicht bemerken, dass Sie das tun müssen), damit sie funktionieren, führen solche Fehler nun aufgrund von [[nodiscard]] zu einer Compilerwarnung.
Hilfe beim Diagnostizieren direkter (Stack-)Allokierungen
Da die projizierten und Implementierungsklassennamen (standardmäßig) identisch sind und sich nur im Namespace unterscheiden, kann man leicht die eine mit der anderen verwechseln und versehentlich eine Implementierung auf dem Stack erstellen, anstatt die Helper der make-Familie zu verwenden. Dies kann in einigen Fällen schwer zu diagnostizieren sein, da das Objekt möglicherweise zerstört wird, während noch Referenzen im Umlauf sind. Eine Assertion berücksichtigt dies jetzt in Debug-Builds. Die Assertion erkennt zwar keine Stapelzuordnung innerhalb einer Coroutine, ist aber dennoch hilfreich, um die meisten solchen Fehler abzufangen.
Weitere Informationen finden Sie unter Diagnose von direkten Zuordnungen.
Verbesserte Capture-Hilfsfunktionen und variadische Delegaten
Dieses Update behebt die Einschränkung mit den Aufnahmehilfsern, indem auch projizierte Typen unterstützt werden. Das kommt bei den Windows-Runtime Interop-APIs hin und wieder vor, wenn diese einen projizierten Typ zurückgeben.
Dieses Update fügt auch Unterstützung für get_strong und get_weak beim Erstellen eines variadischen Delegaten hinzu (nicht für Windows-Runtime).
Unterstützung von verzögerter Zerstörung und sicherem QI während der Zerstörung
Es ist nicht ungewöhnlich, im Destruktor eines Laufzeitklassenobjekts eine Methode aufzurufen, die den Referenzzähler vorübergehend erhöht. Wenn die Verweisanzahl wieder auf null sinkt, wird das Objekt ein zweites Mal zerstört. In einer XAML-Anwendung müssen Sie möglicherweise eine QueryInterface (QI) in einem Destruktor ausführen, um eine Bereinigungsimplementierung nach oben oder unten in der Hierarchie aufzurufen. Der Referenzzähler des Objekts ist jedoch bereits auf null gesunken, sodass auch dieses QI einen Sprung des Referenzzählers darstellt.
Dieses Update fügt Unterstützung für die Entprellung der Referenzzählung hinzu und stellt sicher, dass ein Objekt, sobald die Zählung null erreicht, nicht wiederbelebt werden kann, während Sie per QI weiterhin alle temporären Referenzen abrufen können, die Sie während der Zerstörung benötigen. Dieses Verfahren ist in bestimmten XAML-Anwendungen/Steuerelementen unvermeidbar, und C++/WinRT ist jetzt robust.
Sie können die Zerstörung verzögern, indem Sie eine statische final_release Funktion für Ihren Implementierungstyp bereitstellen. Der letzte verbleibende Zeiger auf das Objekt wird in Form eines std::unique_ptr an Ihr final_release übergeben. Sie können dann den Besitz dieses Zeigers in einen anderen Kontext verschieben. Es ist sicher, dass Sie den Zeiger auf QI bewegen, ohne eine doppelte Zerstörung auszulösen. Die Nettoänderung der Bezugsanzahl muss jedoch an dem Punkt null sein, an dem Sie das Objekt destruktieren.
Der Rückgabewert von final_release kann ein asynchrones Vorgangsobjekt wie void oder winrt::fire_and_forget sein.
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.
}
};
Im folgenden Beispiel wird final_release aufgerufen, sobald die MainPage veröffentlicht wurde (zum letzten Mal). Diese Funktion wartet fünf Sekunden lang (im Threadpool) und setzt dann ihre Ausführung mit dem Dispatcher der Seite fort (wofür QI/AddRef/Release erforderlich ist, damit dies funktioniert). Anschließend wird eine Ressource in diesem UI-Thread bereinigt. Und schließlich wird die unique_ptr gelöscht, wodurch der MainPage-Destruktor tatsächlich aufgerufen wird. Auch in diesem Destruktor wird DataContext aufgerufen, der ein QI für IFrameworkElement erfordert.
Sie müssen Ihre final_release nicht als Coroutine implementieren. Aber das funktioniert, und es macht es sehr einfach, die Zerstörung in einen anderen Thread zu verschieben, was in diesem Beispiel geschieht.
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;
}
};
Weitere Informationen finden Sie unter Verzögerte Zerstörung.
Verbesserte Unterstützung für die Vererbung einzelner Schnittstellen im COM-Stil
Neben der Windows-Runtime Programmierung wird C++/WinRT auch verwendet, um COM-only-APIs zu erstellen und zu nutzen. Mit diesem Update kann ein COM-Server implementiert werden, auf dem eine Schnittstellenhierarchie vorhanden ist. Dies ist für die Windows-Runtime nicht erforderlich. Sie ist jedoch für einige COM-Implementierungen erforderlich.
Korrekte Handhabung von out Params
Es kann schwierig sein, mit out Params zu arbeiten, insbesondere Windows-Runtime Arrays. Mit diesem Update ist C++/WinRT im Umgang mit out-Parametern und Arrays deutlich robuster und fehlertoleranter – unabhängig davon, ob diese Parameter über eine Sprachprojektion eingehen oder von einem COM-Entwickler stammen, der die rohe ABI nutzt und dabei den Fehler macht, Variablen nicht konsistent zu initialisieren. In beiden Fällen macht C++/WinRT jetzt das Richtige, wenn es darum geht, projizierte Typen an die ABI zu übergeben (und dabei alle Ressourcen ordnungsgemäß freizugeben), und wenn es darum geht, Parameter, die über die ABI übergeben werden, auf null zu setzen oder zu bereinigen.
Ereignisse behandeln jetzt zuverlässig ungültige Token
Die winrt::event-Implementierung behandelt jetzt ordnungsgemäß den Fall, in dem die Remove-Methode mit einem ungültigen Tokenwert aufgerufen wird (ein Wert, der nicht im Array vorhanden ist).
Lokale Coroutine-Variablen werden jetzt zerstört, bevor die Coroutine zurückgegeben wird.
Die herkömmliche Implementierung eines Coroutine-Typs kann dazu führen, dass lokale Variablen innerhalb der Coroutine nachdem die Coroutine zurückkehrt/abgeschlossen ist zerstört werden (anstatt vor der finalen Aussetzung). Die Wiederaufnahme eines Kellners wird nun bis zur endgültigen Aussetzung zurückgestellt, um dieses Problem zu vermeiden und andere Vorteile zu ersparen.
Neuigkeiten und Änderungen in Windows SDK Version 10.0.17763.0 (Windows 10, Version 1809)
Die folgende Tabelle enthält Neuigkeiten und Änderungen für C++/WinRT in der Windows SDK Version 10.0.17763.0 (Windows 10, Version 1809).
| Neue oder geänderte Funktion | Weitere Informationen |
|---|---|
| Die Änderung wird abgebrochen. Damit es kompiliert werden kann, hängt C++/WinRT nicht von Headern aus dem Windows SDK ab. | Siehe Isolation aus Windows SDK-Headerdateien unten. |
| Das Visual Studio Projektsystemformat wurde geändert. | Hier erfahren Sie, wie Sie Ihr C++/WinRT-Projekt auf eine spätere Version des Windows SDK umstellen. |
| Es gibt neue Funktionen und Basisklassen, mit denen Sie ein Auflistungsobjekt an eine Windows-Runtime-Funktion übergeben oder eigene Sammlungseigenschaften und Auflistungstypen implementieren können. | Siehe Sammlungen mit C++/WinRT. |
| Sie können die {Binding} -Markuperweiterung mit Ihren C++/WinRT-Laufzeitklassen verwenden. | Weitere Informationen und Codebeispiele finden Sie in der Übersicht über die Datenbindung. |
| Die Unterstützung für das Abbrechen eines Coroutine ermöglicht es Ihnen, einen Abbruchrückruf zu registrieren. | Weitere Informationen und Codebeispiele finden Sie unter Abbrechen eines asynchronen Vorgangs und Abbruchrückrufe. |
| Wenn Sie einen Delegaten erstellen, der auf eine Memberfunktion verweist, können Sie beim Registrieren des Handlers eine starke oder schwache Referenz auf das aktuelle Objekt festlegen (anstelle eines rohen this-Zeigers). | Weitere Informationen und Codebeispiele finden Sie im Unterabschnitt Wenn Sie eine Memberfunktion als Delegat verwenden im Abschnitt Sicherer Zugriff auf den this-Zeiger mit einem Ereignisbehandlungsdelegaten. |
| Es wurden Fehler behoben, die durch Visual Studios verbesserte Konformität mit dem C++-Standard aufgedeckt wurden. Die LLVM- und Clang-Toolkette wird auch besser genutzt, um die Standardskonformität von C++/WinRT zu überprüfen. | Das Problem, das unter "Warum wird mein neues Projekt nicht kompiliert" beschrieben, tritt nicht mehr auf? Ich verwende Visual Studio 2017 (Version 15.8.0 oder höher) und SDK-Version 17134 |
Andere Änderungen.
-
Die Änderung wird abgebrochen.
winrt::get_abi(winrt::hstring const&) liefert jetzt
void*stattHSTRINGzurück. Sie könnenstatic_cast<HSTRING>(get_abi(my_hstring));verwenden, um eine HSTRING abzurufen. Siehe Interoperabilität mit dem HSTRING der ABI. -
Die Änderung wird abgebrochen.
winrt::put_abi(winrt::hstring&) gibt jetzt
void**stattHSTRING*zurück. Sie könnenreinterpret_cast<HSTRING*>(put_abi(my_hstring));verwenden, um eine HSTRING* abzurufen. Siehe Interoperabilität mit dem HSTRING der ABI. -
Die Änderung wird abgebrochen. HRESULT wird jetzt als winrt::hresult projiziert. Wenn Sie ein HRESULT (zum Durchführen der Typüberprüfung oder zur Unterstützung von Typeigenschaften) benötigen, können
static_castSie ein winrt::hresult verwenden. Andernfalls wird winrt::hresult zu HRESULT, sofern Sieunknwn.heinbinden, bevor Sie C++/WinRT-Header einbinden. -
Die Änderung wird abgebrochen. GUID wird jetzt als winrt::guid projiziert. Für apIs, die Sie implementieren, müssen Sie winrt::guid für GUID-Parameter verwenden. Andernfalls wird winrt::guid zu GUID konvertiert, sofern Sie
unknwn.heinbinden, bevor Sie C++/WinRT-Header einbinden. Siehe Die GUID-Struktur der ABI verwenden. - Die Änderung wird abgebrochen. Der winrt::handle_type-Konstruktor wurde dadurch gehärtet, dass er explizit gemacht wurde (es ist jetzt schwieriger, falschen Code damit zu schreiben). Wenn Sie einen unformatierten Handlewert zuweisen müssen, rufen Sie stattdessen die funktion handle_type::attach auf.
-
Die Änderung wird abgebrochen. Die Signaturen von WINRT_CanUnloadNow und WINRT_GetActivationFactory wurden geändert. Sie dürfen diese Funktionen überhaupt nicht deklarieren. Fügen Sie stattdessen
winrt/base.hein (das automatisch eingebunden wird, wenn Sie eine beliebige C++/WinRT-Windows-Namespaceheaderdatei einbinden), um die Deklarationen dieser Funktionen einzubinden. - Für die winrt::clock-Struktur sind from_FILETIME/to_FILETIME zugunsten von from_file_time/to_file_time veraltet.
- Vereinfachte APIs, die IBuffer-Parameter erwarten. Die meisten APIs bevorzugen Sammlungen oder Arrays. Wir haben jedoch gefühlt, dass wir es einfacher machen sollten, APIs aufzurufen, die auf IBuffer basieren. Dieses Update bietet direkten Zugriff auf die Daten hinter einer IBuffer-Implementierung . Es verwendet dieselbe Datenbenennungskonvention wie die von den C++-Standardbibliothekscontainern verwendete. Diese Konvention vermeidet auch Konflikte mit Metadatennamen, die konventionell mit einem Großbuchstaben beginnen.
- Verbesserte Codegenerierung: verschiedene Verbesserungen zur Reduzierung der Codegröße, zur Verbesserung des Inlinings und zur Optimierung des Factory-Cachings.
- Unnötige Rekursion entfernt. Wenn sich die Befehlszeile auf einen Ordner bezieht, anstatt auf einen bestimmten
.winmdOrdner, sucht dascppwinrt.exeTool nicht mehr rekursiv nach.winmdDateien. Dascppwinrt.exeTool behandelt jetzt auch Duplikate intelligenter, wodurch es gegenüber Benutzerfehlern und schlecht gebildeten.winmdDateien stabiler wird. - Gehärtete intelligente Zeiger. Bisher konnten die Ereignis-Revoker nicht zurückgenommen werden, wenn ihnen per Move-Assignment ein neuer Wert zugewiesen wurde. Dadurch wurde ein Problem aufgedeckt, bei dem Smart-Pointer-Klassen Selbstzuweisungen nicht zuverlässig verarbeiteten und dessen Ursache in der Strukturvorlage „winrt::com_ptr“ lag. winrt::com_ptr wurde korrigiert, und die Ereignis-Revoker wurden so angepasst, dass sie die Move-Semantik korrekt behandeln, sodass sie bei einer Zuweisung aufgehoben werden.
Important
Wichtige Änderungen wurden an der C++/WinRT Visual Studio Extension (VSIX) vorgenommen, sowohl in Version 1.0.181002.2 als auch später in Version 1.0.190128.4. Ausführliche Informationen zu diesen Änderungen und deren Auswirkungen auf Ihre vorhandenen Projekte Visual Studio Unterstützung für C++/WinRT und frühere Versionen der VSIX-Erweiterung.
Isolation von Windows SDK-Headerdateien
Dies ist möglicherweise eine bahnbrechende Änderung für Ihren Code.
Damit es kompiliert werden kann, hängt C++/WinRT nicht mehr von Headerdateien aus dem Windows SDK ab. Headerdateien in der C-Laufzeitbibliothek (C Run-Time Library, CRT) und der C++ Standard Template Library (STL) enthalten auch keine Windows SDK-Header. Und das verbessert die Einhaltung von Standards, vermeidet versehentliche Abhängigkeiten und reduziert die Anzahl der Makros, vor denen Sie schützen müssen.
Diese Unabhängigkeit bedeutet, dass C++/WinRT jetzt portierbarer ist und Standards kompatibel ist, und es wird die Möglichkeit erweitert, dass es zu einer cross-compiler- und plattformübergreifenden Bibliothek wird. Dies bedeutet auch, dass die C++/WinRT-Header keine nachteiligen Makros sind.
Wenn Sie es bisher C++/WinRT überlassen haben, beliebige Windows-Header in Ihr Projekt einzubinden, müssen Sie diese nun selbst einbinden. In jedem Fall ist es stets empfehlenswert, die Header-Dateien, die Sie benötigen, explizit einzubinden, anstatt sich darauf zu verlassen, dass eine andere Bibliothek sie für Sie einbindet.
Derzeit sind die einzigen Ausnahmen von der Isolierung von Windows SDK-Headerdateien Intrinsics und Numerik. Es gibt keine bekannten Probleme mit diesen letzten verbleibenden Abhängigkeiten.
In Ihrem Projekt können Sie die Interoperabilität mit den Windows SDK-Headern bei Bedarf erneut aktivieren. Sie können z. B. eine COM-Schnittstelle implementieren (die in IUnknown verwurzelt ist). Für dieses Beispiel binden Sie unknwn.h ein, bevor Sie C++/WinRT-Header einbinden. Dies bewirkt, dass die C++/WinRT-Basisbibliothek verschiedene Hooks zur Unterstützung klassischer COM-Schnittstellen aktiviert. Ein Codebeispiel finden Sie unter Erstellen von COM-Komponenten mit C++/WinRT. Geben Sie ebenso explizit alle anderen Windows SDK-Header an, die Typen und/oder Funktionen deklarieren, die Sie aufrufen möchten.
So aktualisieren Sie Ihr C++/WinRT-Projekt auf eine höhere Version des Windows SDK
Die Methode zum Retargetieren Ihres Projekts, das wahrscheinlich zu den wenigsten Compiler- und Linker-Problem führt, ist auch das arbeitsintensivste. Diese Methode umfasst das Erstellen eines neuen Projekts (für die Windows SDK-Version Ihrer Wahl) und anschließendes Kopieren von Dateien in Ihr neues Projekt aus Dem alten. Sie können Abschnitte aus Ihren alten .vcxproj- und .vcxproj.filters-Dateien einfach übernehmen, sodass Sie die Dateien nicht in Visual Studio hinzufügen müssen.
Es gibt jedoch zwei weitere Möglichkeiten, Ihr Projekt in Visual Studio neu auszurichten.
- Wechseln Sie zur Projekteigenschaft Allgemein>Windows SDK-Version, und wählen Sie "Alle Konfigurationen" und "Alle Plattformen" aus. Legen Sie Windows SDK-Version auf die Version fest, auf die Sie abzielen möchten.
- Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten, klicken Sie auf "Projekte aktualisieren", wählen Sie die Version(n) aus, die Sie als Ziel festlegen möchten, und klicken Sie dann auf "OK".
Wenn nach der Verwendung einer dieser beiden Methoden Compiler- oder Linkerfehler auftreten, können Sie versuchen, die Lösung zu bereinigen (>BuildClean Solution und/oder manuell alle temporären Ordner und Dateien zu löschen), bevor Sie erneut versuchen, zu erstellen.
Wenn der C++-Compiler "error C2039: 'IUnknown': is not a member of '`global namespace''" ausgibt, fügen Sie #include <unknwn.h> am Anfang Ihrer pch.h-Datei hinzu, bevor Sie C++/WinRT-Header einbinden.
Möglicherweise müssen Sie danach auch #include <hstring.h> hinzufügen.
Wenn der C++-Linker "Fehler LNK2019: nicht aufgelöstes externes Symbol _WINRT_CanUnloadNow@0, auf die in der Funktion _VSDesignerCanUnloadNow@0 verwiesen wird" ausgibt, können Sie das beheben, indem Sie #define _VSDESIGNER_DONT_LOAD_AS_DLL zu Ihrer pch.h-Datei hinzufügen.
Windows developer