Apa yang baru di C++/WinRT

Saat versi C++/WinRT berikutnya dirilis, topik ini menjelaskan apa yang baru, dan apa yang berubah.

Rollup perbaikan/penambahan terbaru per Maret 2020

Waktu build hingga 23% lebih pendek

Tim kompilator C++/WinRT dan C++ telah berkolaborasi untuk melakukan segala yang mungkin untuk mempersingkat waktu build. Kami telah melakukan pored atas analitik kompilator untuk mencari tahu bagaimana internal C++/WinRT dapat direstrukturisasi untuk membantu pengkompilasi C++ menghilangkan overhead waktu kompilasi, serta bagaimana kompiler C++ itu sendiri dapat ditingkatkan untuk menangani pustaka C++/WinRT. C++/WinRT telah dioptimalkan untuk pengkompilasi; dan kompilator telah dioptimalkan untuk C++/WinRT.

Mari kita ambil contoh skenario terburuk dalam membangun header yang telah dikompilasi sebelumnya (PCH) yang berisi setiap header namespace proyeksi C++/WinRT tunggal.

Versi Ukuran PCH (byte) Waktu (s)
C++/WinRT mulai Juli, dengan Visual C++ 16.3 3,004,104,632 31
versi 2.0.200316.3 dari C++/WinRT, dengan Visual C++ 16.5 2,393,515,336 24

Pengurangan ukuran 20%, dan pengurangan 23% dalam waktu build.

Dukungan MSBuild yang disempurnakan

Kami telah menginvestasikan banyak pekerjaan untuk meningkatkan dukungan MSBuild untuk berbagai pilihan skenario yang berbeda.

Penembolokan pabrik yang lebih cepat

Kami telah meningkatkan inlining cache pabrik untuk jalur panas sebaris yang lebih baik, yang mengarah pada eksekusi yang lebih cepat.

Peningkatan tersebut tidak memengaruhi ukuran kode—seperti yang dijelaskan di bawah ini dalam Code-gen EH yang dioptimalkan, jika aplikasi Anda menggunakan penanganan pengecualian C++ sangat, maka Anda dapat menyusutkan biner Anda dengan menggunakan /d2FH4 opsi , yang aktif secara default dalam proyek baru yang dibuat dengan Visual Studio 2019 16.3, dan yang lebih baru.

Tinju yang lebih efisien

Ketika digunakan dalam aplikasi XAML, winrt::box_value sekarang lebih efisien (lihat Boxing dan unboxing). Aplikasi yang melakukan banyak tinju juga akan melihat pengurangan ukuran kode.

Dukungan untuk menerapkan antarmuka COM yang mengimplementasikan IInspectable

Jika Anda perlu menerapkan antarmuka COM (non-Windows-Runtime) yang kebetulan menerapkan IInspectable, maka Anda sekarang dapat melakukannya dengan C++/WinRT. Lihat antarmuka COM yang mengimplementasikan IInspectable.

Peningkatan penguncian modul

Kontrol atas penguncian modul sekarang memungkinkan skenario hosting kustom dan penghapusan penguncian tingkat modul sama sekali. Lihat Peningkatan penguncian modul.

Dukungan untuk informasi kesalahan non-Windows-Runtime

Beberapa API (bahkan beberapa API Runtime Windows) melaporkan kesalahan tanpa menggunakan API asal kesalahan Windows Runtime. Dalam kasus seperti itu, C++/WinRT sekarang kembali menggunakan info kesalahan COM. Lihat dukungan C++/WinRT untuk informasi kesalahan non-WinRT.

Mengaktifkan dukungan modul C++

Dukungan modul C++ kembali, tetapi hanya dalam bentuk eksperimental. Fitur ini belum lengkap di pengkompilasi C++.

Penerbitan ulang koroutine yang lebih efisien

Koroutin C++/WinRT sudah berkinerja baik, tetapi kami terus mencari cara untuk meningkatkannya. Lihat Meningkatkan skalabilitas penerbitan ulang koroutine.

Pembantu asinkron when_all dan when_any baru

Fungsi pembantu when_all membuat objek IAsyncAction yang selesai ketika semua yang disediakan dapat ditunggu telah selesai. Pembantu when_any membuat IAsyncAction yang selesai ketika salah satu awaitable yang disediakan telah selesai.

Lihat Menambahkan when_any asinkron helper dan Menambahkan when_all asinkron helper.

Pengoptimalan dan penambahan lainnya

Selain itu, banyak perbaikan bug dan pengoptimalan dan penambahan kecil telah diperkenalkan, termasuk berbagai peningkatan untuk menyederhanakan penelusuran kesalahan dan untuk mengoptimalkan implementasi internal dan default. Ikuti tautan ini untuk daftar lengkap: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed.

Berita, dan perubahan, di C++/WinRT 2.0

Untuk informasi selengkapnya tentang C++/WinRT Visual Studio Extension (VSIX), paket NuGet Microsoft.Windows.CppWinRT, dan alat— cppwinrt.exe termasuk cara memperoleh dan menginstalnya—lihat Dukungan Visual Studio untuk C++/WinRT, XAML, ekstensi VSIX, dan paket NuGet.

Perubahan pada C++/WinRT Visual Studio Extension (VSIX) untuk versi 2.0

  • Visualizer debug sekarang mendukung Visual Studio 2019; serta terus mendukung Visual Studio 2017.
  • Banyak perbaikan bug telah dibuat.

Perubahan pada paket NuGet Microsoft.Windows.CppWinRT untuk versi 2.0

  • Alat cppwinrt.exe ini sekarang disertakan dalam paket NuGet Microsoft.Windows.CppWinRT, dan alat ini menghasilkan header proyeksi platfom untuk setiap proyek sesuai permintaan. Akibatnya, alat ini cppwinrt.exe tidak lagi tergantung pada Windows SDK (meskipun, alat ini masih dikirim dengan SDK karena alasan kompatibilitas).
  • cppwinrt.exe sekarang menghasilkan header proyeksi di bawah setiap folder perantara khusus platform/konfigurasi ($IntDir) untuk mengaktifkan build paralel.
  • Dukungan build C++/WinRT (alat peraga/target) sekarang sepenuhnya didokumenkan, jika Anda ingin menyesuaikan file proyek Anda secara manual. Lihat readme paket NuGet Microsoft.Windows.CppWinRT.
  • Banyak perbaikan bug telah dibuat.

Perubahan pada C++/WinRT untuk versi 2.0

Sumber terbuka

Alat ini cppwinrt.exe mengambil file metadata Windows Runtime (.winmd), dan menghasilkan darinya pustaka C++ standar berbasis file header yang memproyeksikan API yang dijelaskan dalam metadata. Dengan demikian, Anda dapat menggunakan API tersebut dari kode C++/WinRT Anda.

Alat ini sekarang merupakan proyek yang sepenuhnya sumber terbuka, tersedia di GitHub. Kunjungi Microsoft/cppwinrt.

pustaka xlang

Pustaka khusus header yang sepenuhnya portabel (untuk mengurai format metadata ECMA-335 yang digunakan oleh Windows Runtime) membentuk dasar semua alat Windows Runtime dan xlang ke depannya. Terutama, kami juga menulis cppwinrt.exe ulang alat dari bawah ke atas menggunakan pustaka xlang. Ini menyediakan kueri metadata yang jauh lebih akurat, memecahkan beberapa masalah lama dengan proyeksi bahasa C++/WinRT.

Lebih sedikit dependensi

Karena pembaca metadata xlang, alat itu cppwinrt.exe sendiri memiliki lebih sedikit dependensi. Hal ini membuatnya jauh lebih fleksibel, serta dapat digunakan dalam lebih banyak skenario—terutama di lingkungan build yang dibatasi. Terutama, itu tidak lagi bergantung pada RoMetadata.dll.   Ini adalah dependensi untuk cppwinrt.exe 2.0.  

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

Semua DLL tersebut tersedia tidak hanya di Windows 10, tetapi sampai ke Windows 7, dan bahkan Windows Vista. Jika Anda menginginkannya, server build lama yang menjalankan Windows 7 sekarang dapat berjalan cppwinrt.exe untuk menghasilkan header C++ untuk proyek Anda. Dengan sedikit pekerjaan, Anda bahkan dapat menjalankan C++/WinRT di Windows 7, jika itu menarik minat Anda.

Berbeda dengan daftar di atas dengan dependensi ini, yang cppwinrt.exe dimiliki 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

Atribut Windows Runtime noexcept

Windows Runtime memiliki atribut baru [noexcept] , yang dapat Anda gunakan untuk menghias metode dan properti Anda di MIDL 3.0. Kehadiran atribut menunjukkan kepada alat pendukung bahwa implementasi Anda tidak melemparkan pengecualian (atau mengembalikan HRESULT yang gagal). Ini memungkinkan proyeksi bahasa untuk mengoptimalkan pembuatan kode dengan menghindari overhead penanganan pengecualian yang diperlukan untuk mendukung panggilan antarmuka biner aplikasi (ABI) yang berpotensi gagal.

C++/WinRT memanfaatkan ini dengan menghasilkan implementasi C++ noexcept dari kode penggunaan dan penulisan. Jika Anda memiliki metode API atau properti yang bebas kegagalan, dan Anda khawatir tentang ukuran kode, maka Anda dapat menyelidiki atribut ini.

Pembuatan kode yang dioptimalkan

C++/WinRT sekarang menghasilkan kode sumber C++ yang lebih efisien (di belakang layar) sehingga pengkompilasi C++ dapat menghasilkan kode biner terkecil dan paling efisien yang mungkin. Banyak peningkatan diarahkan untuk mengurangi biaya penanganan pengecualian dengan menghindari informasi yang tidak perlu dilepaskan. Biner yang menggunakan kode C++/WinRT dalam jumlah besar akan melihat pengurangan ukuran kode sekitar 4%. Kode ini juga lebih efisien (berjalan lebih cepat) karena jumlah instruksi yang berkurang.

Peningkatan ini mengandalkan fitur interop baru yang tersedia untuk Anda juga. Semua jenis C++/WinRT yang merupakan pemilik sumber daya sekarang menyertakan konstruktor untuk mengambil kepemilikan secara langsung, menghindari pendekatan dua langkah sebelumnya.

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

IStringable projected(raw, take_ownership_from_abi);

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

Pembuatan kode penanganan pengecualian (EH) yang dioptimalkan

Perubahan ini melengkapi pekerjaan yang telah dilakukan oleh tim pengoptimal Microsoft C++ untuk mengurangi biaya penanganan pengecualian. Jika Anda menggunakan antarmuka biner aplikasi (ARI) (seperti COM) sangat dalam kode Anda, maka Anda akan mengamati banyak kode mengikuti pola ini.

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

C++/WinRT sendiri menghasilkan pola ini untuk setiap API yang diimplementasikan. Dengan ribuan fungsi API, pengoptimalan apa pun di sini bisa signifikan. Di masa lalu, pengoptimal tidak akan mendeteksi bahwa blok tangkapan tersebut semuanya identik, sehingga menduplikasi banyak kode di sekitar setiap ABI (yang pada gilirannya berkontribusi pada keyakinan bahwa menggunakan pengecualian dalam kode sistem menghasilkan biner besar). Namun, dari Visual Studio 2019 pada, pengkompilasi C++ melipat semua funclet tangkapan tersebut, dan hanya menyimpan yang unik. Hasilnya adalah pengurangan ukuran kode lebih lanjut dan keseluruhan 18% untuk biner yang sangat bergantung pada pola ini. Kode EH sekarang lebih efisien daripada menggunakan kode pengembalian, tetapi juga kekhawatiran tentang biner yang lebih besar sekarang menjadi hal dari masa lalu.

Peningkatan build inkremental

Alat ini cppwinrt.exe sekarang membandingkan output file header/sumber yang dihasilkan dengan konten file yang ada di disk, dan hanya menulis file jika file sebenarnya telah berubah. Ini menghemat banyak waktu dengan I/O disk, dan memastikan bahwa file tidak dianggap "kotor" oleh pengkompilasi C++. Hasilnya adalah kompilasi ulang dihindari, atau dikurangi, dalam banyak kasus.

Antarmuka generik sekarang semuanya dihasilkan

Karena pembaca metadata xlang, C++/WinRT sekarang menghasilkan semua antarmuka berparameter, atau umum dari metadata. Antarmuka seperti Windows::Foundation::Collections::IVector<T> sekarang dihasilkan dari metadata daripada ditulis tangan di winrt/base.h. Hasilnya adalah bahwa ukuran winrt/base.h telah dipotong menjadi dua, dan bahwa pengoptimalan dihasilkan tepat ke dalam kode (yang sulit dilakukan dengan pendekatan yang digulung tangan).

Penting

Antarmuka seperti contoh yang diberikan sekarang muncul di header namespace masing-masing, bukan di winrt/base.h. Jadi, jika Anda belum melakukannya, Anda harus menyertakan header namespace yang sesuai untuk menggunakan antarmuka.

Pengoptimalan komponen

Pembaruan ini menambahkan dukungan untuk beberapa pengoptimalan keikutsertaan tambahan untuk C++/WinRT, yang dijelaskan di bagian di bawah ini. Karena pengoptimalan ini melanggar perubahan (yang mungkin perlu Anda buat perubahan kecil pada dukungan), Anda harus mengaktifkannya secara eksplisit. Di Visual Studio, atur properti proyek Properti>Umum C++/WinRT>Dioptimalkan ke Ya. Itu memiliki efek menambahkan <CppWinRTOptimized>true</CppWinRTOptimized> ke file proyek Anda. Dan memiliki efek yang sama seperti menambahkan -opt[imize] sakelar saat memanggil cppwinrt.exe dari baris perintah.

Proyek baru (dari templat proyek) akan digunakan -opt secara default.

Konstruksi seragam, dan akses implementasi langsung

Kedua pengoptimalan ini memungkinkan akses langsung komponen Anda ke jenis implementasinya sendiri, bahkan ketika hanya menggunakan jenis yang diproyeksikan. Tidak perlu menggunakan make, make_self, atau get_self jika Anda hanya ingin menggunakan permukaan API publik. Panggilan Anda akan dikompilasi ke bawah untuk mengarahkan panggilan ke dalam implementasi, dan panggilan tersebut bahkan mungkin sepenuhnya diinlin.

Untuk informasi selengkapnya, dan contoh kode, lihat Ikut serta dalam konstruksi seragam, dan akses implementasi langsung.

Pabrik yang dihapus jenis

Pengoptimalan ini menghindari dependensi #include sehingga tidak perlu dikompresi module.g.cpp ulang setiap kali kelas implementasi tunggal terjadi perubahan. Hasilnya adalah peningkatan performa build.

Lebih cerdas dan efisien module.g.cpp untuk proyek besar dengan beberapa libs

File module.g.cpp sekarang juga berisi dua pembantu tambahan yang dapat disusun, bernama winrt_can_unload_now, dan winrt_get_activation_factory. Ini telah dirancang untuk proyek yang lebih besar di mana DLL terdiri dari sejumlah libs, masing-masing dengan kelas runtime sendiri. Dalam situasi itu, Anda perlu menjahit dllGetActivationFactory dan DllCanUnloadNow secara manual. Pembantu ini membuatnya jauh lebih mudah bagi Anda untuk melakukan itu, dengan menghindari kesalahan asal yang memacu. cppwinrt.exe Bendera alat -lib ini juga dapat digunakan untuk memberi setiap lib sendiri awalnya (bukan winrt_xxx) sehingga fungsi setiap lib dapat diberi nama individual, dan dengan demikian digabungkan secara tidak ambigu.

Dukungan Coroutine

Dukungan Coroutine disertakan secara otomatis. Sebelumnya, dukungan berada di beberapa tempat, yang kami rasa terlalu membatasi. Dan kemudian untuk sementara untuk v2.0, winrt/coroutine.h file header diperlukan, tetapi itu tidak lagi diperlukan. Karena antarmuka asinkron Windows Runtime sekarang dihasilkan, daripada ditulis tangan, antarmuka tersebut sekarang berada di winrt/Windows.Foundation.h. Selain lebih dapat dipertahankan dan dapat didukung, itu berarti bahwa pembantu koroutin seperti resume_foreground tidak lagi harus ditangguhkan ke akhir header namespace tertentu. Sebaliknya, mereka dapat lebih alami menyertakan dependensi mereka. Ini lebih lanjut memungkinkan resume_foreground untuk mendukung tidak hanya melanjutkan pada Windows::UI::Core::CoreDispatcher tertentu, tetapi sekarang juga dapat mendukung melanjutkan pada Windows::System::D ispatcherQueue tertentu. Sebelumnya, hanya satu yang dapat didukung; tetapi tidak keduanya, karena definisi hanya dapat berada di satu namespace.

Berikut adalah contoh dukungan 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);
}

Pembantu koroutine sekarang juga dihiasi dengan [[nodiscard]], sehingga meningkatkan kegunaan mereka. Jika Anda lupa (atau tidak menyadari bahwa Anda harus) co_await mereka bekerja maka, karena [[nodiscard]], kesalahan tersebut sekarang menghasilkan peringatan kompilator.

Bantuan dengan mendiagnosis alokasi langsung (tumpukan)

Karena nama kelas yang diproyeksikan dan implementasi (secara default) sama, dan hanya berbeda dengan namespace layanan, dimungkinkan untuk salah satu untuk yang lain, dan untuk secara tidak sengaja membuat implementasi pada tumpukan, daripada menggunakan keluarga pembantu make. Ini mungkin sulit untuk didiagnosis dalam beberapa kasus, karena objek dapat dihancurkan saat referensi yang luar biasa masih dalam penerbangan. Pernyataan sekarang mengambil ini, untuk build debug. Meskipun pernyataan tidak mendeteksi alokasi tumpukan di dalam koroutin, namun sangat membantu dalam menangkap sebagian besar kesalahan tersebut.

Untuk informasi selengkapnya, lihat Mendiagnosis alokasi langsung.

Pembantu penangkapan yang ditingkatkan, dan delegasi variadik

Pembaruan ini memperbaiki batasan dengan pembantu penangkapan dengan mendukung jenis yang diproyeksikan juga. Ini muncul sekarang dan kemudian dengan WINDOWS Runtime interop API, ketika mereka mengembalikan jenis yang diproyeksikan.

Pembaruan ini juga menambahkan dukungan untuk get_strong dan get_weak saat membuat delegasi variadik (non-Windows Runtime).

Dukungan untuk penghancuran yang ditangguhkan dan QI yang aman selama penghancuran

Tidak jarang di destruktor objek kelas runtime untuk memanggil metode yang sementara menabrak jumlah referensi. Saat jumlah referensi kembali ke nol, objek akan merusak untuk kedua kalinya. Dalam aplikasi XAML, Anda mungkin perlu melakukan QueryInterface (QI) di destruktor, untuk memanggil beberapa implementasi pembersihan ke atas atau ke bawah hierarki. Tetapi jumlah referensi objek telah mencapai nol, sehingga QI juga merupakan pantulan jumlah referensi.

Pembaruan ini menambahkan dukungan untuk mendebounasi jumlah referensi, memastikan bahwa setelah mencapai nol, pembaruan tidak pernah dapat dibangkitkan; sementara masih memungkinkan Anda untuk QI untuk sementara yang Anda butuhkan selama penghancuran. Prosedur ini tidak dapat dicabut dalam aplikasi/kontrol XAML tertentu, dan C++/WinRT sekarang tahan terhadapnya.

Anda dapat menangguhkan penghancuran dengan menyediakan fungsi final_release statis pada jenis implementasi Anda. Pointer terakhir yang tersisa ke objek, dalam bentuk std::unique_ptr, diteruskan ke final_release Anda. Anda kemudian dapat memilih untuk memindahkan kepemilikan pointer tersebut ke beberapa konteks lain. Aman bagi Anda untuk QI pointer tanpa memicu penghancuran ganda. Tetapi perubahan bersih ke jumlah referensi harus nol pada saat Anda menghapus objek.

Nilai pengembalian final_release dapat berupa void, objek operasi asinkron seperti IAsyncAction, atau 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.
    }
};

Dalam contoh di bawah ini, setelah MainPage dirilis (untuk waktu terakhir), final_release dipanggil. Fungsi itu menghabiskan lima detik menunggu (pada kumpulan utas), dan kemudian dilanjutkan menggunakan Dispatcher halaman (yang mengharuskan QI/AddRef/Release berfungsi). Kemudian membersihkan sumber daya pada utas UI tersebut. Dan akhirnya membersihkan unique_ptr, yang menyebabkan destruktor MainPage benar-benar dipanggil. Bahkan dalam destruktor itu, DataContext dipanggil, yang memerlukan QI untuk IFrameworkElement.

Anda tidak perlu mengimplementasikan final_release Anda sebagai koroutine. Tetapi itu berhasil, dan itu membuatnya sangat mudah untuk memindahkan penghancuran ke utas yang berbeda, yang merupakan apa yang terjadi dalam contoh ini.

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;
    }
};

Untuk informasi selengkapnya, lihat Penghancuran yang ditangguhkan.

Dukungan yang disempurnakan untuk pewarisan antarmuka tunggal gaya COM

Selain untuk pemrograman Windows Runtime, C++/WinRT juga digunakan untuk menulis dan menggunakan API khusus COM. Pembaruan ini memungkinkan untuk mengimplementasikan server COM di mana ada hierarki antarmuka. Ini tidak diperlukan untuk Windows Runtime; tetapi diperlukan untuk beberapa implementasi COM.

Penanganan out param yang benar

Mungkin sulit untuk bekerja dengan out param; terutama array Windows Runtime. Dengan pembaruan ini, C++/WinRT jauh lebih kuat dan tahan terhadap kesalahan dalam hal out param dan array; apakah parameter tersebut tiba melalui proyeksi bahasa, atau dari pengembang COM yang menggunakan ABI mentah, dan siapa yang membuat kesalahan untuk tidak menginisialisasi variabel secara konsisten. Dalam kedua kasus, C++/WinRT sekarang melakukan hal yang benar dalam hal menyerahkan jenis yang diproyeksikan ke ABI (dengan mengingat untuk merilis sumber daya apa pun), dan ketika datang ke nol keluar atau membersihkan parameter yang tiba di ABI.

Peristiwa sekarang menangani token yang tidak valid dengan andal

Implementasi winrt::event sekarang dengan anggun menangani kasus di mana metode penghapusannya dipanggil dengan nilai token yang tidak valid (nilai yang tidak ada dalam array).

Variabel lokal coroutine sekarang dihancurkan sebelum coroutine kembali

Cara tradisional untuk menerapkan jenis koroutine dapat memungkinkan variabel lokal dalam koroutin dihancurkan setelah coroutine kembali/selesai (bukan sebelum suspensi akhir). Dimulainya kembali setiap pelayan sekarang ditangguhkan sampai penangguhan akhir, untuk menghindari masalah ini dan untuk mengumpulkan manfaat lain.

Berita, dan perubahan, di Windows SDK versi 10.0.17763.0 (Windows 10, versi 1809)

Tabel di bawah ini berisi berita dan perubahan untuk C++/WinRT di Windows SDK versi 10.0.17763.0 (Windows 10, versi 1809).

Fitur baru atau yang diubah Info selengkapnya
Melanggar perubahan. Agar dapat dikompilasi, C++/WinRT tidak bergantung pada header dari Windows SDK. Lihat Isolasi dari file header Windows SDK, di bawah ini.
Format sistem proyek Visual Studio telah berubah. Lihat Cara menargetkan ulang proyek C++/WinRT Anda ke versi Windows SDK yang lebih baru, di bawah ini.
Ada fungsi dan kelas dasar baru untuk membantu Anda meneruskan objek koleksi ke fungsi Windows Runtime, atau untuk menerapkan properti koleksi dan jenis koleksi Anda sendiri. Lihat Koleksi dengan C++/WinRT.
Anda dapat menggunakan ekstensi markup {Binding} dengan kelas runtime C++/WinRT Anda. Untuk informasi selengkapnya, dan contoh kode, lihat Gambaran umum pengikatan data.
Dukungan untuk membatalkan coroutine memungkinkan Anda mendaftarkan panggilan balik pembatalan. Untuk informasi selengkapnya, dan contoh kode, lihat Membatalkan operasi asinkron, dan panggilan balik pembatalan.
Saat membuat delegasi yang menunjuk ke fungsi anggota, Anda dapat membuat referensi yang kuat atau lemah ke objek saat ini (bukan mentah penunjuk ini ) pada titik di mana handler terdaftar. Untuk informasi selengkapnya, dan contoh kode, lihat jika Anda menggunakan fungsi anggota sebagai sub-bagian delegasi di bagian Brankas mengakses pointer ini dengan delegasi penanganan peristiwa.
Bug diperbaiki yang terungkap oleh peningkatan kesuaian Visual Studio dengan standar C++. Toolchain LLVM dan Clang juga lebih baik dimanfaatkan untuk memvalidasi kesamaan standar C++/WinRT. Anda tidak akan lagi mengalami masalah yang dijelaskan dalam Mengapa proyek baru saya tidak akan dikompilasi? Saya menggunakan Visual Studio 2017 (versi 15.8.0 atau yang lebih baru), dan SDK versi 17134

Perubahan lainnya.

  • Melanggar perubahan. winrt::get_abi(winrt::hstring const&) sekarang mengembalikan alih-alih void*HSTRING. Anda dapat menggunakan static_cast<HSTRING>(get_abi(my_hstring)); untuk mendapatkan HSTRING. Lihat Mengoperasikan dengan HSTRING ABI.
  • Melanggar perubahan. winrt::p ut_abi(winrt::hstring&) sekarang mengembalikan alih-alih void**HSTRING*. Anda dapat menggunakan reinterpret_cast<HSTRING*>(put_abi(my_hstring)); untuk mendapatkan HSTRING*. Lihat Mengoperasikan dengan HSTRING ABI.
  • Melanggar perubahan. HRESULT sekarang diproyeksikan sebagai winrt::hresult. Jika Anda memerlukan HRESULT (untuk melakukan pemeriksaan jenis, atau untuk mendukung sifat jenis), maka Anda dapat static_cast winrt ::hresult. Jika tidak, winrt::hresult dikonversi ke HRESULT, selama Anda menyertakan unknwn.h sebelum Anda menyertakan header C++/WinRT apa pun.
  • Melanggar perubahan. GUID sekarang diproyeksikan sebagai winrt::guid. Untuk API yang Anda terapkan, Anda harus menggunakan winrt::guid untuk parameter GUID. Jika tidak, winrt::guid dikonversi ke GUID, selama Anda menyertakan unknwn.h sebelum Anda menyertakan header C++/WinRT apa pun. Lihat Mengoperasikan dengan struktur GUID ABI.
  • Melanggar perubahan. Konstruktor winrt::handle_type telah diperkuat dengan membuatnya eksplisit (sekarang lebih sulit untuk menulis kode yang salah dengannya). Jika Anda perlu menetapkan nilai handel mentah, panggil fungsi handle_type::attach sebagai gantinya.
  • Melanggar perubahan. Tanda tangan WINRT_CanUnloadNow dan WINRT_GetActivationFactory telah berubah. Anda tidak boleh mendeklarasikan fungsi-fungsi ini. Sebagai gantinya, sertakan winrt/base.h (yang secara otomatis disertakan jika Anda menyertakan file header namespace layanan Windows C++/WinRT) untuk menyertakan deklarasi fungsi-fungsi ini.
  • Untuk struktur winrt::clock, from_FILETIME/to_FILETIME tidak digunakan lagi demi from_file_time/to_file_time.
  • API yang disederhanakan yang mengharapkan parameter IBuffer . Sebagian besar API lebih suka koleksi, atau array. Tetapi kita merasa bahwa kita harus mempermudah untuk memanggil API yang mengandalkan IBuffer. Pembaruan ini menyediakan akses langsung ke data di balik implementasi IBuffer . Ini menggunakan konvensi penamaan data yang sama dengan yang digunakan oleh kontainer Pustaka Standar C++. Konvensi itu juga menghindari tabrakan dengan nama metadata yang secara konvensional dimulai dengan huruf besar.
  • Pembuatan kode yang ditingkatkan: berbagai peningkatan untuk mengurangi ukuran kode, meningkatkan inlining, dan mengoptimalkan penembolokan pabrik.
  • Menghapus rekursi yang tidak perlu. Ketika baris perintah mengacu pada folder, daripada ke folder tertentu .winmd, cppwinrt.exe alat tidak lagi mencari file secara .winmd rekursif. Alat ini cppwinrt.exe juga sekarang menangani duplikat dengan lebih cerdas, membuatnya lebih tahan terhadap kesalahan pengguna, dan file yang terbentuk .winmd dengan buruk.
  • Pointer pintar yang diperkeras. Sebelumnya, pencabut peristiwa gagal dicabut saat memindahkan nilai baru yang ditetapkan. Ini membantu mengungkap masalah di mana kelas penunjuk pintar tidak menangani penugasan mandiri dengan andal; berakar dalam templat struct winrt::com_ptr. winrt::com_ptr telah diperbaiki, dan pencabut peristiwa diperbaiki untuk menangani pemindahan semantik dengan benar sehingga mereka mencabut setelah penugasan.

Penting

Perubahan penting dilakukan pada C++/WinRT Visual Studio Extension (VSIX), keduanya dalam versi 1.0.181002.2, lalu yang lebih baru dalam versi 1.0.190128.4. Untuk detail perubahan ini, dan bagaimana perubahan tersebut memengaruhi proyek Anda yang ada, dukungan Visual Studio untuk C++/WinRT dan versi ekstensi VSIX sebelumnya.

Isolasi dari file header Windows SDK

Ini berpotensi menjadi perubahan yang melanggar untuk kode Anda.

Agar dapat dikompilasi, C++/WinRT tidak lagi bergantung pada file header dari Windows SDK. File header di pustaka run-time C (CRT) dan Pustaka Templat Standar (STL) C++ juga tidak menyertakan header Windows SDK apa pun. Dan itu meningkatkan kepatuhan standar, menghindari dependensi yang tidak disengaja, dan sangat mengurangi jumlah makro yang harus Anda jaga.

Kemandirian ini berarti bahwa C++/WinRT sekarang lebih portabel dan sesuai standar, dan semakin memajukan kemungkinannya menjadi pustaka lintas kompilator dan lintas platform. Ini juga berarti bahwa header C++/WinRT tidak terpengaruh makro yang merugikan.

Jika sebelumnya Anda meninggalkannya ke C++/WinRT untuk menyertakan header Windows apa pun dalam proyek Anda, maka Sekarang Anda harus menyertakannya sendiri. Bagaimanapun, dalam hal apa pun, selalu praktik terbaik untuk secara eksplisit menyertakan header yang Anda andalkan, dan tidak meninggalkannya ke pustaka lain untuk menyertakannya untuk Anda.

Saat ini, satu-satunya pengecualian untuk isolasi file header Windows SDK adalah untuk intrinsik, dan numerik. Tidak ada masalah yang diketahui dengan dependensi terakhir yang tersisa ini.

Dalam proyek, Anda dapat mengaktifkan kembali interop dengan header Windows SDK jika perlu. Anda mungkin, misalnya, ingin mengimplementasikan antarmuka COM (berakar di IUnknown). Untuk contoh tersebut, sertakan unknwn.h sebelum Anda menyertakan header C++/WinRT apa pun. Melakukannya menyebabkan pustaka dasar C++/WinRT mengaktifkan berbagai kait untuk mendukung antarmuka COM klasik. Untuk contoh kode, lihat Menulis komponen COM dengan C++/WinRT. Demikian pula, secara eksplisit menyertakan header Windows SDK lainnya yang mendeklarasikan jenis dan/atau fungsi yang ingin Anda panggil.

Cara menargetkan ulang proyek C++/WinRT Anda ke versi Windows SDK yang lebih baru

Metode untuk menargetkan ulang proyek Anda yang kemungkinan akan menghasilkan masalah kompilator dan linker terkecil juga merupakan yang paling padat karya. Metode tersebut melibatkan pembuatan proyek baru (menargetkan versi Windows SDK pilihan Anda), lalu menyalin file ke proyek baru Anda dari proyek lama Anda. Akan ada bagian lama .vcxproj dan .vcxproj.filters file yang dapat Anda salin untuk menyimpan Anda menambahkan file di Visual Studio.

Namun, ada dua cara lain untuk menargetkan ulang proyek Anda di Visual Studio.

  • Buka properti proyek Versi Windows SDK Umum>, dan pilih Semua Konfigurasi dan Semua Platform. Atur Versi Windows SDK ke versi yang ingin Anda targetkan.
  • Di Penjelajah Solusi, klik kanan simpul proyek, klik Target ulang Proyek, pilih versi yang ingin Anda targetkan, lalu klik OK.

Jika Anda mengalami kesalahan pengkompilasi atau linker setelah menggunakan salah satu dari dua metode ini, maka Anda dapat mencoba membersihkan solusi (Build>Clean Solution dan/atau menghapus semua folder dan file sementara secara manual) sebelum mencoba membangun lagi.

Jika pengompilasi C++ menghasilkan "kesalahan C2039: 'IUnknown': bukan anggota ''namespace global''", tambahkan #include <unknwn.h> ke bagian atas file Anda pch.h (sebelum Anda menyertakan header C++/WinRT apa pun).

Anda mungkin juga perlu menambahkan #include <hstring.h> setelah itu.

Jika linker C++ menghasilkan "kesalahan LNK2019: simbol eksternal yang tidak terselesaikan _WINRT_CanUnloadNow@0 direferensikan dalam _VSDesignerCanUnloadNow@0 fungsi", maka Anda dapat mengatasinya dengan menambahkan #define _VSDESIGNER_DONT_LOAD_AS_DLL ke file Anda pch.h .