C++/WinRT の新機能

以降のバージョンの C++/WinRT がリリースされると、このトピックでは新機能と変更点について説明します。

2020 年 3 月時点での最近の改善点と追加機能のまとめ

最大 23% 短いビルド時間

C++/WinRT および C++ コンパイラ チームは、ビルド時間を短縮するために可能な限りすべてを行うために共同作業を行っています。 C++/WinRT の内部を再構築して、C++ コンパイラがコンパイル時のオーバーヘッドをなくすのに役立つ方法と、C++/WinRT ライブラリを処理するために C++ コンパイラ自体を改善する方法を理解するために、コンパイラ分析について説明しました。 C++/WinRT はコンパイラ用に最適化されています。コンパイラは C++/WinRT 用に最適化されています。

たとえば、C++/WinRT プロジェクション名前空間ヘッダーを 1 つ 1 つ含む事前コンパイル済みヘッダー (PCH) を構築する最悪のシナリオを考えてみましょう。

Version PCH サイズ (バイト) 時間 (秒)
7 月の C++/WinRT と Visual C++ 16.3 3,004,104,632 31
Visual C++ 16.5 を使用した C++/WinRT のバージョン 2.0.200316.3 2,393,515,336 24

サイズが 20% 削減され、ビルド時間が 23% 削減されます。

MSBuild のサポートの強化

さまざまなシナリオの大規模な選択に対する MSBuild サポートの改善に多くの作業を費やしてきました。

さらに高速なファクトリ キャッシュ

インライン ホット パスを改善するために、ファクトリ キャッシュのインライン化が改善され、実行が高速化されました。

この改善はコード サイズには影響しません。以下の「最適化された EH コード生成」で説明するように、アプリケーションで C++ 例外処理が頻繁に使用されている場合は、/d2FH4 オプションを使用してバイナリを圧縮できます。これは、Visual Studio 2019 16.3 以降で作成された新しいプロジェクトで既定でオンになっています。

より効率的なボクシング

XAML アプリケーションで使用すると、 winrt::box_value がより効率的になりました ( ボックス化とボックス化解除を参照)。 ボックス化を多用するアプリケーションでも、コード サイズの減少が見られます。

IInspectable を実装する COM インターフェイスの実装のサポート

IInspectable を実装するだけの (Windows-Runtime以外の) COM インターフェイスを実装する必要がある場合は、C++/WinRT で実装できるようになりました。 IInspectable を実装する COM インターフェイスを参照してください。

モジュール ロックの機能強化

モジュール ロックを制御することで、カスタム ホスティング シナリオと、モジュール レベルのロックを完全に解除できるようになりました。 モジュール ロックの機能強化を参照してください。

Windows-Runtime 以外のエラー情報のサポート

一部の API (一部のWindows ランタイム API も含む) では、エラーの発生元 API Windows ランタイム使用せずにエラーが報告されます。 このような場合、C++/WinRT は COM エラー情報の使用にフォールバックするようになりました。 WinRT 以外のエラー情報については、C++/WinRT のサポートを参照してください

C++ モジュールのサポートを有効にする

C++ モジュールのサポートは戻ってきましたが、試験的な形式でのみサポートされます。 この機能は C++ コンパイラではまだ完了していません。

より効率的なコルーチン再開

C++/WinRT コルーチンは既に良好なパフォーマンスを発揮していますが、引き続き改善する方法を探しています。 コルーチン再開のスケーラビリティの向上を参照してください。

新しい when_allwhen_any 非同期ヘルパー

when_all ヘルパー関数は、指定されたすべての待機可能オブジェクトが完了したときに完了する IAsyncAction オブジェクトを作成します。 when_any ヘルパーは、指定された待機可能オブジェクトのいずれかが完了したときに完了する IAsyncAction を生成します。

when_any 非同期ヘルパーの追加およびwhen_all 非同期ヘルパーの追加を参照してください。

その他の最適化と追加

さらに、デバッグを簡略化したり、内部実装と既定の実装を最適化したりするためのさまざまな機能強化など、多くのバグ修正と軽微な最適化と追加が導入されています。 完全な一覧については、次のリンクを参照してください: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed

C++/WinRT 2.0 のニュースと変更

C++/WinRT Visual Studio 拡張機能 (VSIX)Microsoft.Windows.CppWinRT NuGet パッケージ、および cppwinrt.exe ツールの詳細については (これらの入手方法とインストール方法を含め)、Visual Studio での C++/WinRT、XAML、VSIX 拡張機能、および NuGet パッケージのサポートを参照してください。

バージョン 2.0 の C++/WinRT Visual Studio拡張機能 (VSIX) の変更

  • デバッグ ビジュアライザーでは、Visual Studio 2019 がサポートされるようになり、Visual Studio 2017 も引き続きサポートされるようになりました。
  • 多数のバグ修正が行われています。

Microsoft.Windows.CppWinRT NuGet パッケージのバージョン 2.0 における変更

  • cppwinrt.exe ツールが Microsoft.Windows.CppWinRT NuGet パッケージに含まれるようになり、そのツールは各プロジェクトについて、必要に応じてプラットフォーム プロジェクション ヘッダーを生成します。 そのため、cppwinrt.exe ツールは Windows SDK に依存しなくなりました (ただし、互換性上の理由から、ツールは SDK に付属しています)。
  • cppwinrt.exe では、並列ビルドを有効にするために、各プラットフォーム/構成固有の中間フォルダー ($IntDir) の下にプロジェクション ヘッダーが生成されるようになりました。
  • プロジェクト ファイルを手動でカスタマイズする場合に備えて、C++/WinRT ビルド サポート (props/targets) が完全に文書化されるようになりました。 Microsoft.Windows.CppWinRT NuGet パッケージの Readme を参照してください。
  • 多数のバグ修正が行われています。

バージョン 2.0 の C++/WinRT への変更

オープンソース

cppwinrt.exe ツールは、Windows ランタイムメタデータ (.winmd) ファイルを取得し、そこから、メタデータに記述されている API を投影するヘッダー ファイルベースの標準 C++ ライブラリを生成します。 そうすることで、C++/WinRT コードからこれらの API を使用できます。

このツールは完全にオープンソースプロジェクトとなり、GitHubで使用できるようになりました。 Microsoft/cppwinrt にアクセスしてください。

xlang ライブラリ

完全に移植可能なヘッダー専用ライブラリ (Windows ランタイムで使用される ECMA-335 メタデータ形式の解析用) は、今後のすべてのWindows ランタイムおよび xlang ツールの基礎を形成します。 特に、xlang ライブラリを使用して、 cppwinrt.exe ツールを一から書き直しました。 これにより、より正確なメタデータ クエリが提供され、C++/WinRT 言語プロジェクションに関するいくつかの長年の問題が解決されます。

依存関係の数を減らします

xlang メタデータ リーダーにより、 cppwinrt.exe ツール自体の依存関係が少なくなります。 これにより、柔軟性が大幅に高くなり、特に制約付きビルド環境でより多くのシナリオで使用できるようになります。 特に、 RoMetadata.dllに依存しなくなりました。   これらは、 cppwinrt.exe 2.0 の依存関係です。  

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

これらの DLL はすべて、Windows 10だけでなく、Windows 7まで、さらにはWindows Vistaまで利用できます。 必要に応じて、Windows 7を実行している古いビルド サーバーをcppwinrt.exe実行して、プロジェクトの C++ ヘッダーを生成できるようになりました。 少しの作業があれば、Windows 7で C++/WinRT を実行することもできます。

上記の一覧と、 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

Windows ランタイム の noexcept 属性

Windows ランタイムには新しい[noexcept]属性があり、MIDL 3.0 でメソッドとプロパティを装飾するために使用できます。 この属性の存在は、実装が例外をスローしない (失敗した HRESULT を返さない) ことをサポートツールに示します。 これにより、言語プロジェクションでは、失敗する可能性があるアプリケーション バイナリ インターフェイス (ABI) 呼び出しをサポートするために必要な例外処理オーバーヘッドを回避することで、コード生成を最適化できます。

C++/WinRT では、使用コードとオーサリング コードの両方の C++ noexcept 実装を生成することで、これを利用します。 失敗しない API メソッドまたはプロパティがあり、コード サイズが心配な場合は、この属性を調査できます。

最適化されたコード生成

C++/WinRT では、C++ コンパイラが可能な限り最小かつ最も効率的なバイナリ コードを生成できるように、(バックグラウンドで) さらに効率的な C++ ソース コードが生成されるようになりました。 多くの機能強化は、不要なアンワインド情報を回避することで、例外処理のコストを削減するために用意されています。 大量の C++/WinRT コードを使用するバイナリでは、コード サイズが約 4% 減少します。 また、命令数が減るため、コードの効率も向上します (より高速に実行されます)。

これらの機能強化は、ユーザーが利用できる新しい相互運用機能にも依存します。 リソース所有者であるすべての C++/WinRT 型に、所有権を直接取得するためのコンストラクターが含まれるようになり、前の 2 段階のアプローチを回避できるようになりました。

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

IStringable projected(raw, take_ownership_from_abi);

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

最適化された例外処理 (EH) コード生成

この変更は、Microsoft C++ オプティマイザー チームが行った作業を補完して、例外処理のコストを削減します。 コード内でアプリケーション バイナリ インターフェイス(ABI)(COM など)を多用していると、このパターンに従うコードを数多く目にすることになります。

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

C++/WinRT 自体は、実装されているすべての API に対してこのパターンを生成します。 何千もの API 関数を使用すると、ここでの最適化が重要になる可能性があります。 以前は、オプティマイザーではこれらの catch ブロックがすべて同じであることが検出されないため、各 ABI の周りに多くのコードが複製されていました (これは、システム コードで例外を使用すると大きなバイナリが生成されるという信念に寄与していました)。 ただし、2019 年Visual Studioから、C++ コンパイラはそれらのすべてのキャッチ 機能を折りたたみ、一意の機能のみを格納します。 その結果、このパターンに大きく依存するバイナリのコード サイズがさらに 18% 減少します。 EH コードはリターン コードを使用するよりも効率的になっただけでなく、より大きなバイナリに関する懸念も過去のものになりました。

増分ビルドの機能強化

cppwinrt.exe ツールは、生成されたヘッダー/ソース ファイルの出力をディスク上の既存のファイルの内容と比較し、ファイルが実際に変更された場合にのみファイルを書き込みます。 これにより、ディスク I/O の時間が大幅に節約され、C++ コンパイラによってファイルが "ダーティ" と見なされないことが保証されます。 その結果、多くの場合、再コンパイルは回避または削減されます。

ジェネリック インターフェイスがすべて生成されるようになりました

xlang メタデータ リーダーにより、C++/WinRT はメタデータからすべてのパラメーター化されたジェネリック インターフェイスを生成するようになりました。 Windows::Foundation::Collections::IVector<T> などのインターフェイスが、winrt/base.hで手動で記述されるのではなく、メタデータから生成されるようになりました。 その結果、 winrt/base.h のサイズが半分にカットされ、最適化がコードに直接生成されます (これは手動によるアプローチでは困難でした)。

Von Bedeutung

この例のようなインターフェイスは、 winrt/base.hではなく、それぞれの名前空間ヘッダーに表示されるようになりました。 そのため、まだ行っていない場合は、インターフェイスを使用するために適切な名前空間ヘッダーを含める必要があります。

コンポーネントの最適化

この更新プログラムでは、以下のセクションで説明する、C++/WinRT に対するいくつかのオプトイン最適化のサポートが追加されました。 これらの最適化は重大な変更であるため (サポートに少し変更を加える必要がある場合があります)、明示的に有効にする必要があります。 Visual Studioで、プロジェクト プロパティの共通プロパティ>C++/WinRT>Optimized[はい] に設定します。 これは、プロジェクト ファイルに <CppWinRTOptimized>true</CppWinRTOptimized> を追加する効果があります。 また、コマンド ラインから-opt[imize]を呼び出すときに cppwinrt.exe スイッチを追加する場合と同じ効果があります。

(プロジェクト テンプレートから) 新しいプロジェクトでは、既定で -opt が使用されます。

均一な構築と直接実装アクセス

これら 2 つの最適化により、投影された型のみを使用している場合でも、コンポーネントは独自の実装型に直接アクセスできます。 単にパブリック API サーフェスを使用する場合は、 makemake_selfget_self を使用する必要はありません。 呼び出しは最終的に実装を直接呼び出すコードへとコンパイルされ、その呼び出しは完全にインライン化されることさえあります。

詳細とコード例については、「 統一された構築へのオプトイン」および「実装への直接アクセス」を参照してください。

型消去ファクトリ

この最適化により、 module.g.cpp の #include 依存関係が回避されるため、1 つの実装クラスが変更されるたびに再コンパイルする必要はありません。 その結果、ビルドのパフォーマンスが向上します。

複数のライブラリを持つ大規模なプロジェクトに対して、よりスマートで効率的なmodule.g.cpp

module.g.cpp ファイルには、winrt_can_unload_now と winrt_get_activation_factory という名前の 2 つの追加のコンポーザブル ヘルパーも含まれるようになりました。 これらは、DLL が多数のライブラリで構成され、それぞれが独自のランタイム クラスを持つ大規模なプロジェクト向けに設計されています。 このような場合は、DLL の DllGetActivationFactoryDllCanUnloadNow を手動で結合する必要があります。 これらのヘルパーを使用すると、スプリアスな発生エラーを回避することで、これを行うのがはるかに簡単になります。 cppwinrt.exe ツールの -lib フラグを使用して、各 lib に (winrt_xxxではなく) 独自のプリアンブルを与え、各 lib の関数を個別に名前を付け、明確に組み合わせることもできます。

コルーチンのサポート

コルーチン サポートは自動的に含まれます。 以前は、サポートは複数の場所に存在していましたが、制限が多すぎると感じていました。 v2.0 では一時的に、 winrt/coroutine.h ヘッダー ファイルが必要でしたが、これは不要になりました。 Windows ランタイム非同期インターフェイスは、手書きではなく生成されるため、winrt/Windows.Foundation.hに存在するようになりました。 保守性とサポート性が高いとは別に、 resume_foreground などのコルーチン ヘルパーを特定の名前空間ヘッダーの末尾に取り付ける必要がなくなったことを意味します。 代わりに、依存関係をより自然に含めることができます。 これにより、resume_foregroundは特定のWindows::UI::Core::CoreDispatcher での再開だけでなく、特定のWindows::System::D ispatcherQueue での再開もサポートできるようになりました。 以前は、サポートできたのは 1 つだけでした。ただし、定義は 1 つの名前空間にのみ存在できるため、両方ではありません。

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

コルーチンヘルパーも [[nodiscard]]で装飾され、使いやすさが向上しました。 それらを機能させるためにco_awaitする必要があることを、忘れていた(または気づいていなかった)場合でも、[[nodiscard]]により、そのようなミスではコンパイラ警告が出るようになりました。

直接 (スタック) 割り当ての診断に関するヘルプ

投影されたクラス名と実装クラス名は (既定では) 同じであり、名前空間によってのみ異なるため、 make ファミリの ヘルパーを使用するのではなく、一方を間違えてスタックに誤って実装を作成する可能性があります。 参照がまだ有効な状態にある間にオブジェクトが破棄される可能性があるため、場合によってはこれを診断するのが難しいことがあります。 アサーションがデバッグ ビルドではこれを検出するようになりました。 アサーションはコルーチン内のスタック割り当てを検出しませんが、そのような間違いのほとんどをキャッチするのに役立ちます。

詳細については、「 直接割り当ての診断」を参照してください。

キャプチャ ヘルパーと可変デリゲートの改善

この更新プログラムは、投影された型もサポートすることで、キャプチャ ヘルパーの制限を修正します。 これは、Windows ランタイム 相互運用 API が投影型を返すときに、ときどき発生します。

この更新プログラムでは、可変 (非Windows ランタイム) デリゲートを作成するときのget_strongとget_weakのサポートも追加されます。

遅延破棄と破棄中の安全な QI のサポート

ランタイム クラス オブジェクトのデストラクターで、参照カウントを一時的に増やすメソッドを呼び出すことは珍しいことではありません。 参照カウントが再び 0 になると、オブジェクトは再度破棄されます。 XAML アプリケーションでは、階層を上下にクリーンアップ実装を呼び出すために、デストラクターで QueryInterface (QI) を実行することが必要になる場合があります。 ただし、オブジェクトの参照カウントは既に 0 に達しているため、QI も参照カウントバウンスを構成します。

この更新プログラムでは、参照カウントにデバウンスを適用する機能が追加され、参照カウントがいったんゼロに達すると二度と復活しないことを保証しつつ、破棄中に必要な一時オブジェクトに対しては引き続き QI を行えるようになりました。 この手順は特定の XAML アプリケーション/コントロールでは避けられません。C++/WinRT はそれに対する回復性を備えています。

実装型に静的 なfinal_release 関数を指定することで、破棄を延期できます。 オブジェクトへの最後の残りのポインター ( std::unique_ptr の形式) が final_releaseに渡されます。 その後、そのポインターの所有権を他のコンテキストに移動することを選択できます。 二重破壊をトリガーせずにポインターを QI しても安全です。 ただし、参照カウントに対する純変更は、オブジェクトを破棄する時点でゼロにする必要があります。

final_releaseの戻り値は、voidIAsyncAction などの非同期操作オブジェクト、または 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.
    }
};

次の例では、 MainPage が解放されると (最後の時間)、 final_release が呼び出されます。 この関数は (スレッド プールで) 5 秒間待機した後、ページの Dispatcher (QI/AddRef/Release が機能する必要があります) を使用して再開します。 その後、その UI スレッド上のリソースがクリーンアップされます。 最後に、 unique_ptrがクリアされ、 MainPage デストラクターが実際に呼び出されます。 そのデストラクターでも DataContext が呼び出され、 IFrameworkElement には QI が必要です。

コルーチンとして final_release を実装する必要はありません。 しかし、それは機能し、この例で起こっていることである別のスレッドに破壊を移動することは非常に簡単です。

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

詳細については、「遅延破棄」を参照してください。

COM スタイルのシングル インターフェイス継承のサポートが強化されました

C++/WinRT は、Windows ランタイム プログラミングの場合と同様に、COM 専用 API の作成と使用にも使用されます。 この更新プログラムにより、インターフェイス階層が存在する COM サーバーを実装できます。 これはWindows ランタイムには必要ありませんが、一部の COM 実装では必要です。

outパラメーターの正しい処理

outパラメーター、特にWindows ランタイム配列を操作するのは難しい場合があります。 この更新により、C++/WinRT は out パラメーターや配列に関して大幅に堅牢になり、言語プロジェクション経由でそれらのパラメーターが渡される場合でも、生の ABI を使用する COM 開発者から渡される場合でも、変数を一貫して初期化しないというミスに対する耐性が大きく向上しました。 どちらの場合も、C++/WinRT は、投影された型を (リソースを解放することを忘れずに) ABI に渡すとき、および ABI 全体で到着するパラメーターをゼロにしたりクリアしたりするときに、正しいことを行うようになりました。

イベントが無効なトークンを確実に処理するようになりました

winrt::event 実装では、無効なトークン値 (配列に存在しない値) を使用して remove メソッドが呼び出されるケースが適切に処理されるようになりました。

コルーチンが戻る前にコルーチンローカル変数が破棄されるようになりました

コルーチン型を実装する従来の方法では、コルーチンの戻り/完了 (最終中断前ではなく) コルーチン内のローカル変数を破棄できる場合があります。 この問題を回避し、他の利点を得るために、待機者の再開は最終的な中断まで延期されるようになりました。

Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) のニュースと変更

次の表に、Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) の C++/WinRT のニュースと変更点を示します。

新機能または変更された機能 詳細情報
破壊的変更。 コンパイルのために、C++/WinRT は Windows SDK のヘッダーに依存しません。 以下の「Windows SDK ヘッダー ファイルからの分離」を参照してください。
Visual Studio プロジェクト システムの形式が変更されました。 以下の「C++/WinRT プロジェクトを新しいバージョンの Windows SDK に再ターゲットする方法」を参照してください。
コレクション オブジェクトをWindows ランタイム関数に渡したり、独自のコレクション プロパティとコレクション型を実装したりするのに役立つ新しい関数と基本クラスがあります。 C++/WinRT を使用したコレクションを参照してください。
{Binding} マークアップ拡張機能は、C++/WinRT ランタイム クラスと共に使用できます。 詳細とコード例については、「 データ バインディングの概要」を参照してください。
コルーチンの取り消しをサポートすることで、キャンセル コールバックを登録できます。 詳細とコード例については、「 非同期操作の取り消し」および「キャンセル コールバック」を参照してください。
メンバー関数を指すデリゲートを作成する際は、ハンドラーを登録する時点で、現在のオブジェクトへの強参照または弱参照を(生の this ポインターではなく)確立できます。 詳細とコード例については、「イベント処理デリゲートを使用してこのポインターに安全にアクセスする」セクションの「メンバー関数をデリゲート サブセクションとして使用する場合」を参照してください。
Visual Studioの C++ 標準への準拠の改善によって発見されたバグが修正されました。 LLVM と Clang ツールチェーンも、C++/WinRT の標準準拠を検証するためにより優れています。 「新しいプロジェクトがコンパイルされない理由」で説明されている問題が発生しなくなりました。Visual Studio 2017 (バージョン 15.8.0 以降) と SDK バージョン 17134 を使用しています

その他の変更。

  • 破壊的変更 winrt::get_abi(winrt::hstring const>) は、void*ではなくHSTRINGを返すようになりました。 static_cast<HSTRING>(get_abi(my_hstring));を使用して HSTRING を取得できます。 ABI の HSTRING との相互運用を参照してください。
  • 破壊的変更 winrt::put_abi(winrt::hstring&) は、HSTRING* ではなく void** を返すようになりました。 reinterpret_cast<HSTRING*>(put_abi(my_hstring));を使用して HSTRING* を取得できます。 ABI の HSTRING との相互運用を参照してください。
  • 破壊的変更。 HRESULT は winrt::hresult として投影されるようになりました。 HRESULT が必要な場合 (型チェックを行う場合、または型の特徴をサポートする場合)、static_castできます。 それ以外の場合、 winrt::hresult は、C++/WinRT ヘッダーを含める前に unknwn.h を含める限り、HRESULT に変換されます。
  • 破壊的変更。 GUID が winrt::guid として投影されるようになりました。 実装する API の場合は、GUID パラメーターに winrt::guid を使用する必要があります。 それ以外の場合、 winrt::guid は、C++/WinRT ヘッダーを含める前に unknwn.h を含める限り、GUID に変換されます。 ABI の GUID 構造体との相互運用を参照してください。
  • 破壊的変更 winrt::handle_type コンストラクターは明示的にすることで強化されました (不適切なコードを記述するのが難しくなりました)。 生のハンドル値を割り当てる必要がある場合は、代わりに handle_type::attach 関数 を呼び出します。
  • 破壊的変更WINRT_CanUnloadNowWINRT_GetActivationFactoryの署名が変更されました。 これらの関数をまったく宣言しないでください。 代わりに、winrt/base.h (C++/WinRT Windows名前空間ヘッダー ファイルを含める場合は自動的に含まれます) を含め、これらの関数の宣言を含めます。
  • winrt::clock 構造体では、from_FILETIME/to_FILETIME は非推奨であり、代わりに from_file_time/to_file_time が推奨されています。
  • IBuffer パラメーターを必要とする簡略化された API。 ほとんどの API では、コレクションまたは配列が優先されます。 しかし、 IBuffer に依存する API を簡単に呼び出す必要があると感じました。 この更新プログラムは、 IBuffer 実装の背後にあるデータへの直接アクセスを提供します。 C++ 標準ライブラリ コンテナーで使用される名前付け規則と同じデータ名前付け規則が使用されます。 この規則では、従来は大文字で始まるメタデータ名との競合も回避されます。
  • コード生成の改善: コード サイズの削減、インライン化の改善、ファクトリ キャッシュの最適化のためのさまざまな機能強化。
  • 不要な再帰を削除しました。 コマンド ラインが特定の .winmdではなくフォルダーを参照する場合、 cppwinrt.exe ツールは .winmd ファイルを再帰的に検索しなくなります。 また、 cppwinrt.exe ツールは重複をよりインテリジェントに処理し、ユーザー エラーや形式の悪い .winmd ファイルに対する回復性を高めます。
  • 強化されたスマート ポインター。 以前は、新しい値の移動割り当て時に、イベント取り消し子を取り消すことができませんでした。 これは、スマート ポインター クラスが確実に自己割り当てを処理できない問題を明らかにするのに役立ちました。 winrt::com_ptr 構造体テンプレートにルート化されています。 winrt::com_ptr が修正され、イベント リボーカーも、代入時に取り消しが行われるよう、移動セマンティクスを正しく扱うように修正されました。

Von Bedeutung

バージョン 1.0.181002.2 とバージョン 1.0.190128.4 以降の両方で、C++/WinRT Visual Studio拡張機能 (VSIX) に対して重要な変更が行われました。 これらの変更の詳細と、それらが既存のプロジェクトにどのような影響を与えるかについては、Visual Studio による C++/WinRT のサポートおよびVSIX 拡張機能の以前のバージョンをご覧ください。

Windows SDK ヘッダー ファイルからの分離

これは、コードの破壊的変更である可能性があります。

コンパイルのために、C++/WinRT は Windows SDK のヘッダー ファイルに依存しなくなりました。 C ランタイム ライブラリ (CRT) および C++ 標準テンプレート ライブラリ (STL) のヘッダー ファイルにも、Windows SDK ヘッダーは含まれません。 これにより、標準のコンプライアンスが向上し、不注意による依存関係が回避され、保護する必要があるマクロの数が大幅に減ります。

この独立性は、C++/WinRT がより移植性があり、標準に準拠していることを意味し、クロスコンパイラおよびクロスプラットフォーム ライブラリになる可能性をさらに高めます。 また、C++/WinRT ヘッダーがマクロに悪影響を与えないことを意味します。

プロジェクトにWindowsヘッダーを含めるために以前に C++/WinRT に任されていた場合は、それらを自分で含める必要があります。 いずれの場合も、依存するヘッダーを明示的に含め、それらを含めるために別のライブラリに任せないようにすることが常にベスト プラクティスです。

現時点では、WINDOWS SDK ヘッダー ファイルの分離に対する唯一の例外は、組み込み関数と数値です。 これらの最後の残りの依存関係に関する既知の問題はありません。

プロジェクトで、必要に応じて、Windows SDK ヘッダーとの相互運用を再度有効にすることができます。 たとえば、( IUnknown にルート化された) COM インターフェイスを実装できます。 その例では、C++/WinRT ヘッダーを含める前に unknwn.h を含めます。 これを行うと、C++/WinRT ベース ライブラリによって、さまざまなフックが従来の COM インターフェイスをサポートできるようになります。 コード例については、「 C++/WinRT を使用して COM コンポーネントを作成する」を参照してください。 同様に、呼び出す型や関数を宣言する他のWindows SDK ヘッダーを明示的に含めます。

C++/WinRT プロジェクトを新しいバージョンの Windows SDK に再ターゲットする方法

コンパイラとリンカーの問題が最も少なくなる可能性があるプロジェクトを再ターゲットする方法も、最も手間がかかります。 この方法では、新しいプロジェクトを作成し (Windows SDK バージョンを選択して)、古いプロジェクトから新しいプロジェクトにファイルをコピーします。 古い.vcxprojファイルと.vcxproj.filtersファイルには、そのままコピーして使えるセクションがあり、Visual Studio でファイルを追加する手間を省けます。

ただし、Visual Studioでプロジェクトを再ターゲットするには、他に 2 つの方法があります。

  • プロジェクト プロパティ [全般>Windows SDK バージョン] に移動し、[すべての構成] と [すべてのプラットフォーム] を選択します。 WINDOWS SDK バージョンをターゲットにするバージョンに設定します。
  • ソリューション エクスプローラーで、プロジェクト ノードを右クリックし、[プロジェクトの再ターゲット] をクリックし、ターゲットにするバージョンを選択して、[OK] をクリックします。

これら 2 つの方法のいずれかを使用した後にコンパイラまたはリンカーエラーが発生した場合は、もう一度ビルドする前に、ソリューション (Build>Clean Solution またはすべての一時フォルダーとファイルを手動で削除してみてください。

C++ コンパイラで "error C2039: 'IUnknown': is not a member of '`global namespace''" というエラーが表示された場合は、#include <unknwn.h>pch.h ファイルの先頭に追加してください(C++/WinRT ヘッダーをインクルードする前)。

その後、 #include <hstring.h> を追加する必要がある場合もあります。

C++ リンカーで "エラー LNK2019: 未解決の外部シンボル _WINRT_CanUnloadNow@0 が関数 _VSDesignerCanUnloadNow@0 で参照されました" と出力された場合は、#define _VSDESIGNER_DONT_LOAD_AS_DLLpch.h ファイルに追加することで解決できます。