C++/WinRT Documentation

repository·master·Indexed 23 days ago

https://github.com/microsoft/cppwinrt

A header-only C++ language projection for the Windows Runtime (WinRT) that enables the use of modern Windows APIs with standard C++17 code. It includes the Microsoft.Windows.CppWinRT NuGet package for build automation, a Visual Studio Extension (VSIX) for debug visualization and templates, and the cppwinrt.exe CLI tool for generating projections and C++20 module interface units (.ixx) from Windows Metadata (.winmd) files.

Tokens
11.3K
Snippets
16
Records
48
Agent score
81%

What's inside C++/WinRT

  1. Features of the C++/WinRT Visual Studio Extension (VSIX)

    master

    The C++/WinRT VSIX provides two primary developer productivity features:

    1. Debug visualization: Enables debug visualization of C++/WinRT types in Visual Studio, providing a debugging experience similar to C#.
    2. Project and item templates: Provides templates to simplify the process of consuming and authoring Windows runtime classes using modern C++.
  2. Use C++/WinRT for Windows Runtime APIs

    master
    C++/WinRT is a header-file-based library that provides a standard C++ language projection for Windows Runtime (WinRT) APIs. It allows you to author and consume modern Windows APIs using any standards-compliant C++17 compiler.
  3. Understand C++/WinRT module names

    master

    C++/WinRT projections are accessed via specific module names:

    • winrt_base: Contains core C++/WinRT types like hstring, com_ptr, and IUnknown. This is re-exported by all namespace modules.
    • winrt_numerics: Contains Windows::Foundation::Numerics types. This is re-exported by winrt_base.
    • winrt.<Namespace>: The per-namespace projection (e.g., winrt.Windows.Foundation).
    | Module | Contents |
    |--------|----------|
    | `winrt_base` | Core C++/WinRT types (`hstring`, `com_ptr`, `IUnknown`, etc.) — re-exported by all namespace modules |
    | `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` |
    | `winrt.<Namespace>` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) |
  4. Three Fundamental Constraints of C++/WinRT Modules

    master

    When working with C++/WinRT modules, you must adhere to these three rules to avoid compiler errors:

    1. No import in PCH: MSVC cannot handle import declarations inside a Precompiled Header (PCH). All module imports must reside in .cpp files or other non-PCH files.
    2. Avoid Include-then-import for WinRT: While MSVC allows #include-ing a header and then import-ing the same content, doing this with C++/WinRT projection headers is extremely expensive for build times. Use import directly whenever possible.
    3. Import-then-include requires WINRT_IMPORT_MODULE: If you have already import-ed a module, #include-ing a header that declares the same types will cause conflicting declaration errors. To safely include WinRT headers after an import (e.g., to support libraries like WIL), define the WINRT_IMPORT_MODULE macro before the #include statement. This turns the header into a mostly no-op.
  5. Rules for sharing and consuming modules

    master

    When working with modules across different projects, follow these constraints to avoid linker errors and ABI mismatches:

    • Component Modules are Private: Do not tag ProjectReferences to component projects with CppWinRTConsumeModule. Instead, each consumer should build its own reference projection from the component's .winmd.
    • Use a Module Builder for Platform SDKs: Only use CppWinRTConsumeModule=true on a dedicated static library project (a Module Builder) designed to compile platform SDK modules. This builder should use flags that produce safe modules (no -opt, no -comp).
    • Filter Scope: CppWinRTModuleInclude and CppWinRTModuleExclude apply to platform, reference, and component projections. Ensure your filters cover all intended namespaces.
    • Compatibility: Ensure the builder and consumer share the same:
      • Configuration: (e.g., both Debug or both Release).
      • Preprocessor Definitions: To ensure identical type layouts.
      • Struct Alignment: Use matching /Zp settings.
      • Language Standard: (e.g., both /std:c++20).
  6. Consume and produce Windows Runtime classes with C++/WinRT

    master

    C++/WinRT uses the discovered metadata to generate different types of headers based on the source:

    Consuming Windows Runtime classes

    For any discovered .winmd file, C++/WinRT creates reference (consuming) projection headers. To use these in your application, simply #include the generated headers from your project's generated files directory.

    Producing Windows Runtime classes

    For any .idl file contained within your project, C++/WinRT creates component (producing) projection headers. Additionally, it generates the necessary templates and skeleton implementations for each runtime class, which are stored in the Generated Files directory.

  7. Use C++20 Modules with C++/WinRT

    master

    C++/WinRT supports C++20 named modules as an alternative to #include-based consumption. Instead of using #include <winrt/Windows.Foundation.h>, you can use the import keyword.

    Example:

    import winrt.Windows.Foundation;

    To consume pre-built platform module IFCs from a referenced project, set the CppWinRTConsumeModule metadata to true on the ProjectReference.

  8. Understand C++/WinRT Module Consolidation (SCC)

    master

    C++20 modules do not allow circular imports. Because WinRT namespaces often have cyclic dependencies (e.g., Windows.Foundation and Windows.Foundation.Collections), C++/WinRT uses Strongly Connected Components (SCC) to consolidate cycles into a single module.

    How it works:

    1. Owner Selection: The alphabetically first namespace in a cycle is chosen as the "owner".
    2. Owner Module: The owner's .ixx file contains the declarations for all namespaces in that cycle. It uses forward declarations and ordered header includes to break the cycle.
    3. Re-export Stubs: All other namespaces in the cycle receive a thin .ixx file that simply uses export import to re-export the owner module.

    Result: Importing any namespace within the cycle (e.g., import winrt.Windows.Foundation; or import winrt.Windows.Foundation.Collections;) resolves to the same underlying module implementation.

  9. Configure Consumer Projects to use a Module Builder

    master

    To consume the shared modules produced by a Module Builder project, configure your consumer project's .vcxproj as follows:

    1. Enable module support and filter namespaces:
    <PropertyGroup>
      <CppWinRTBuildModule>true</CppWinRTBuildModule>
      <CppWinRTModuleInclude>MyCompany.MyComponent</CppWinRTModuleInclude>
      <CppWinRTModuleExclude>Microsoft.UI;Microsoft.Web</CppWinRTModuleExclude>
    </PropertyGroup>
    1. Reference the Module Builder project with CppWinRTConsumeModule=true:
    <ItemGroup>
      <ProjectReference Include="..\ModuleBuilder\ModuleBuilder.vcxproj">
        <CppWinRTConsumeModule>true</CppWinRTConsumeModule>
      </ProjectReference>
    </ItemGroup>

    Setting CppWinRTConsumeModule to true tells the build system to use the builder's pre-built platform IFCs instead of re-compiling them locally.

    <PropertyGroup>
      <CppWinRTBuildModule>true</CppWinRTBuildModule>
      <CppWinRTModuleInclude>MyCompany.MyComponent</CppWinRTModuleInclude>
      <CppWinRTModuleExclude>Microsoft.UI;Microsoft.Web</CppWinRTModuleExclude>
    </PropertyGroup>
    <ItemGroup>
      <ProjectReference Include="..\ModuleBuilder\ModuleBuilder.vcxproj">
        <CppWinRTConsumeModule>true</CppWinRTConsumeModule>
      </ProjectReference>
    </ItemGroup>
  10. Create a non-XAML Universal Windows App (UWP) with C++/WinRT

    master
    This project template provides a starting point for creating a Universal Windows App (UWP) that does not rely on the XAML framework. It demonstrates how to use the C++/WinRT SDK platform projection headers specifically for the Windows.ApplicationModel.Core namespace to manage application lifecycle and core functionality in a code-only environment.
  11. Consume third-party Windows Runtime components (WinMD)

    master

    To consume a third-party component provided as a .winmd file, follow these steps:

    1. Add Reference: In Visual Studio, right-click the References project node and select Add Reference.... Browse to and select the .winmd file you wish to consume.
    2. Generate Headers: Build the project once. This generates the necessary projection headers for the referenced WinMD file within the Generated Files subfolder.
    3. Include and Use: Include the generated projection headers in your pch.h or source code to access the projected classes.
  12. Install C++/WinRT via NuGet

    master

    For most developers, you should not build C++/WinRT from source. Instead, download and install the latest version using the official NuGet package to integrate the language projection into your Windows Runtime (WinRT) projects.

    http://aka.ms/cppwinrt/nuget