使用 C++/WinRT 的 Windows 執行階段元件Windows Runtime components with C++/WinRT

本主題說明如何使用 c + +/WinRT 來建立和取用 Windows 執行階段元件 — ,該元件可從使用任何 Windows 執行階段語言建立的通用 Windows 應用程式中呼叫。This topic shows how to use C++/WinRT to create and consume a Windows Runtime component—a component that's callable from a Universal Windows app built using any Windows Runtime language.

在 c + + 中建立 Windows 執行階段元件有幾個原因/WinrtThere are several reasons for building a Windows Runtime component in C++/WinRT.

  • 在複雜或需要大量運算的作業中享有 c + + 的效能優勢。To enjoy the performance advantage of C++ in complex or computationally intensive operations.
  • 重複使用已撰寫並測試的標準 c + + 程式碼。To reuse standard C++ code that's already written and tested.
  • 若要將 Win32 功能公開給以撰寫的通用 Windows 平臺 (UWP) 應用程式,例如 c #。To expose Win32 functionality to a Universal Windows Platform (UWP) app written in, for example, C#.

一般情況下,當您撰寫 c + +/WinRT 元件時,您可以使用 standard c + + 程式庫中的類型和內建類型,但在應用程式二進位介面 (ABI) 界限(您將資料傳入和寫入其他封裝中的程式碼) .winmdIn general, when you author your C++/WinRT component, you can use types from the standard C++ library, and built-in types, except at the application binary interface (ABI) boundary where you're passing data to and from code in another .winmd package. 在 ABI 上,使用 Windows 執行階段類型。At the ABI, use Windows Runtime types. 此外,在您的 c + +/WinRT 程式碼中,請使用委派和事件之類的型別,來執行可從元件引發並以其他語言處理的事件。In addition, in your C++/WinRT code, use types such as delegate and event to implement events that can be raised from your component and handled in another language. 如需 c + +/Winrt 的詳細資訊,請參閱c + +/WinRTSee C++/WinRT for more info about C++/WinRT.

本主題的其餘部分將逐步引導您瞭解如何在 c + +/WinRT 中撰寫 Windows 執行階段元件,以及如何從應用程式使用它。The remainder of this topic walks you through how to author a Windows Runtime component in C++/WinRT, and then how to consume it from an application.

您將在本主題中建立的 Windows 執行階段元件包含代表溫度計的執行時間類別。The Windows Runtime component that you'll build in this topic contains a runtime class representing a thermometer. 本主題也會示範取用溫度計執行時間類別的核心應用程式,並呼叫函式來調整溫度。The topic also demonstrates a Core App that consumes the thermometer runtime class, and calls a function to adjust the temperature.

注意

如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 與 NuGet 套件 (一起提供專案範本和建置支援) 的資訊,請參閱 C++/WinRT 的 Visual Studio 支援For info about installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support), see Visual Studio support for C++/WinRT.

重要

如需一些基本概念和詞彙,以協助了解如何以 C++/WinRT 使用及撰寫執行階段類別,請參閱使用 C++/WinRT 來使用 API使用 C++/WinRT 撰寫 APIFor essential concepts and terms that support your understanding of how to consume and author runtime classes with C++/WinRT, see Consume APIs with C++/WinRT and Author APIs with C++/WinRT.

建立 Windows 執行階段元件 (ThermometerWRC) Create a Windows Runtime component (ThermometerWRC)

請先在 Microsoft Visual Studio 中,建立新的專案。Begin by creating a new project in Microsoft Visual Studio. 建立 ** (c + +/WinRT) 專案的 Windows 執行階段元件 ** ,並 將它 命名為 "溫度計 Windows 執行階段 Component" ) 的 (。Create a Windows Runtime Component (C++/WinRT) project, and name it ThermometerWRC (for "thermometer Windows Runtime component"). 確定已取消核取 [將方案和專案放置於同一個目錄]。Make sure that Place solution and project in the same directory is unchecked. 以 Windows SDK 最新的正式推出版本 (即非預覽版本) 為目標。Target the latest generally-available (that is, not preview) version of the Windows SDK. 命名專案 ThermometerWRC 可讓您使用本主題中其餘步驟的最簡單體驗。Naming the project ThermometerWRC will give you the easiest experience with the rest of the steps in this topic.

尚未建置專案。Don't build the project yet.

新建立的專案中包含一個名為 Class.idl 的檔案。The newly-created project contains a file named Class.idl. 在方案總管中,將該檔案 Thermometer.idl 重新命名 (重新命名 .idl 檔案也會自動將相依的 .h.cpp 檔案重新命名)。In Solution Explorer, rename that file Thermometer.idl (renaming the .idl file automatically renames the dependent .h and .cpp files, too). 以下面的清單取代 Thermometer.idl 的內容。Replace the contents of Thermometer.idl with the listing below.

// Thermometer.idl
namespace ThermometerWRC
{
    runtimeclass Thermometer
    {
        Thermometer();
        void AdjustTemperature(Single deltaFahrenheit);
    };
}

儲存檔案。Save the file. 目前,專案不會建立完成,但現在建立是很好的作法,因為它會產生您將在其中執行 溫度計 執行時間類別的原始程式碼檔。The project won't build to completion at the moment, but building now is a useful thing to do because it generates the source code files in which you'll implement the Thermometer runtime class. 因此請繼續並立即建置 (您可預期在這個階段看到的建置錯誤有找不到 Class.hClass.g.h有關)。So go ahead and build now (the build errors you can expect to see at this stage have to do with Class.h and Class.g.h not being found).

在建置程序期間,執行 midl.exe 工具建立元件的 Windows 執行階段中繼資料檔案 (其為 \ThermometerWRC\Debug\ThermometerWRC\ThermometerWRC.winmd)。During the build process, the midl.exe tool is run to create your component's Windows Runtime metadata file (which is \ThermometerWRC\Debug\ThermometerWRC\ThermometerWRC.winmd). 然後,執行 cppwinrt.exe 工具 (有 -component 選項) 產生原始碼檔案在撰寫您的元件中支援您。Then, the cppwinrt.exe tool is run (with the -component option) to generate source code files to support you in authoring your component. 這些檔案包含存根,可讓您開始執行您在 IDL 中宣告的 溫度計 執行時間類別。These files include stubs to get you started implementing the Thermometer runtime class that you declared in your IDL. 這些虛設常式為 \ThermometerWRC\ThermometerWRC\Generated Files\sources\Thermometer.hThermometer.cppThose stubs are \ThermometerWRC\ThermometerWRC\Generated Files\sources\Thermometer.h and Thermometer.cpp.

以滑鼠右鍵按一下專案節點,然後按一下 [在檔案總管中開啟資料夾]。Right-click the project node and click Open Folder in File Explorer. 這會在檔案總管中開啟專案資料夾。This opens the project folder in File Explorer. 然後,從 \ThermometerWRC\ThermometerWRC\Generated Files\sources\ 資料夾將虛設常式檔案 Thermometer.hThermometer.cpp 複製到包含專案檔案的資料夾中,也就是 \ThermometerWRC\ThermometerWRC\ 並取代目的地中的檔案。There, copy the stub files Thermometer.h and Thermometer.cpp from the folder \ThermometerWRC\ThermometerWRC\Generated Files\sources\ and into the folder that contains your project files, which is \ThermometerWRC\ThermometerWRC\, and replace the files in the destination. 現在要開啟 Thermometer.hThermometer.cpp,並實作我們的執行階段類別。Now, let's open Thermometer.h and Thermometer.cpp and implement our runtime class. 在中 Thermometer.h ,將新的私用成員新增至實 (*而非*溫度計的 factory 實) 。In Thermometer.h, add a new private member to the implementation (not the factory implementation) of Thermometer.

// Thermometer.h
...
namespace winrt::ThermometerWRC::implementation
{
    struct Thermometer : ThermometerT<Thermometer>
    {
        ...

    private:
        float m_temperatureFahrenheit { 0.f };
    };
}
...

在中 Thermometer.cpp ,執行 AdjustTemperature 方法,如下列清單所示。In Thermometer.cpp, implement the AdjustTemperature method as shown in the listing below.

// Thermometer.cpp
...
namespace winrt::ThermometerWRC::implementation
{
    void Thermometer::AdjustTemperature(float deltaFahrenheit)
    {
        m_temperatureFahrenheit += deltaFahrenheit;
    }
}

您也必須從這兩個檔案中刪除 static_assertYou'll also need to delete the static_assert from both files.

如果有任何警告妨礙您建置,則加以解決或將專案屬性 C/C++ > 一般 > 視警告為錯誤 設定為 No (/WX-) ,並再試一次建置專案。If any warnings prevent you from building, then either resolve them or set the project property C/C++ > General > Treat Warnings As Errors to No (/WX-), and build the project again.

建立 (ThermometerCoreApp) 的核心應用程式,以測試 Windows 執行階段元件Create a Core App (ThermometerCoreApp) to test the Windows Runtime component

現在,在您的 ThermometerWRC 方案中建立新的專案,或在新的 (中) 。Now create a new project (either in your ThermometerWRC solution, or in a new one). 建立 ** (c + +/WinRT) 專案的核心應用程式 ** ,並將其命名為 ThermometerCoreAppCreate a Core App (C++/WinRT) project, and name it ThermometerCoreApp. 如果兩個專案都在相同的方案中,請將 ThermometerCoreApp 設定為啟始專案。Set ThermometerCoreApp as the startup project if the two projects are in the same solution.

注意

如稍早所述,您 Windows 執行階段元件的 Windows 執行階段中繼資料檔案, (其名為 ThermometerWRC) 的專案會建立在資料夾中 \ThermometerWRC\Debug\ThermometerWRC\As mentioned earlier, the Windows Runtime metadata file for your Windows Runtime component (whose project you named ThermometerWRC) is created in the folder \ThermometerWRC\Debug\ThermometerWRC\. 該路徑的第一個區段是包含解決方案檔案的資料夾名稱;下一個區段是名為 Debug 的子目錄;最後一個區段是為 Windows 執行階段元件所命名的子目錄。The first segment of that path is the name of the folder that contains your solution file; the next segment is the subdirectory of that named Debug; and the last segment is the subdirectory of that named for your Windows Runtime component. 如果您未將專案命名為 ThermometerWRC,則您的中繼資料檔案將會位於資料夾中 \<YourProjectName>\Debug\<YourProjectName>\If you didn't name your project ThermometerWRC, then your metadata file will be in the folder \<YourProjectName>\Debug\<YourProjectName>\.

現在,在您的核心應用程式專案中 (ThermometerCoreApp) 、加入參考,然後流覽至 \ThermometerWRC\Debug\ThermometerWRC\ThermometerWRC.winmd (或加入專案對專案參考(如果兩個專案都在相同的方案) 中)。Now, in your Core App project (ThermometerCoreApp), add a reference, and browse to \ThermometerWRC\Debug\ThermometerWRC\ThermometerWRC.winmd (or add a project-to-project reference, if the two projects are in the same solution). 按一下 [新增],然後按一下 [確定]。Click Add, and then OK. 現在建立 ThermometerCoreAppNow build ThermometerCoreApp. 在不太可能發生的情況下,您看到承載檔案 readme.txt 不存在的錯誤,請從 Windows 執行階段元件專案中排除該檔案,然後重建 ThermometerCoreAppIn the unlikely event that you see an error that the payload file readme.txt doesn't exist, exclude that file from the Windows Runtime component project, rebuild it, then rebuild ThermometerCoreApp.

在建置程序期間,執行 cppwinrt.exe 工具將被參考的 .winmd 檔案處理到包含投影類型的原始碼檔案中,在使用元件裡支援您。During the build process, the cppwinrt.exe tool is run to process the referenced .winmd file into source code files containing projected types to support you in consuming your component. 適用於您元件執行階段類別的投影類型標頭 —名為ThermometerWRC.h—會在資料夾 \ThermometerCoreApp\ThermometerCoreApp\Generated Files\winrt\ 中產生。The header for the projected types for your component's runtime classes—named ThermometerWRC.h—is generated into the folder \ThermometerCoreApp\ThermometerCoreApp\Generated Files\winrt\.

App.cpp 中包含該標頭。Include that header in App.cpp.

// App.cpp
...
#include <winrt/ThermometerWRC.h>
...

此外,在中 App.cpp ,加入下列程式碼以具現化 溫度計 物件 (使用投影的型別預設的函式) ,然後在溫度計物件上呼叫方法。Also in App.cpp, add the following code to instantiate a Thermometer object (using the projected type's default constructor), and call a method on the thermometer object.

struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{
    ThermometerWRC::Thermometer m_thermometer;
    ...
    
    void OnPointerPressed(IInspectable const &, PointerEventArgs const & args)
    {
        m_thermometer.AdjustTemperature(1.f);
        ...
    }
    ...
};

每次您按一下視窗時,就會遞增溫度計物件的溫度。Each time you click the window, you increment the thermometer object's temperature. 如果您想要逐步執行程式碼,以確認應用程式確實呼叫 Windows 執行階段元件,您可以設定中斷點。You can set breakpoints if you want to step through the code to confirm that the application really is calling into the Windows Runtime component.

後續步驟Next steps

若要將更多功能或新的 Windows 執行階段類型新增至 c + +/WinRT Windows 執行階段元件,您可以遵循如上所示的相同模式。To add even more functionality, or new Windows Runtime types, to your C++/WinRT Windows Runtime component, you can follow the same patterns shown above. 首先,使用 IDL 來定義您想要公開的功能。First, use IDL to define the functionality you want to expose. 然後,在 Visual Studio 中建立專案,以產生存根的執行。Then build the project in Visual Studio to generate a stub implementation. 然後視需要完成執行。And then complete the implementation as appropriate. 使用您的 Windows 執行階段元件的應用程式,可以看到您在 IDL 中定義的任何方法、屬性和事件。Any methods, properties, and events that you define in IDL are visible to the application that consumes your Windows Runtime Component. 如需 IDL 的詳細資訊,請參閱 Microsoft 介面定義語言3.0 簡介For more info about IDL, see Introduction to Microsoft Interface Definition Language 3.0.

如需如何將事件加入 Windows 執行階段元件的範例,請參閱 在 c + + 中撰寫事件/WinRTFor an example of how to add an event to your Windows Runtime Component, see Author events in C++/WinRT.

疑難排解Troubleshooting

徵狀Symptom 補救方法Remedy
在 C++/WinRT 應用程式中,當取用一個使用 XAML 的 C# Windows 執行階段元件時,編譯器會產生格式為 " 'MyNamespace_XamlTypeInfo': is not a member of 'winrt::MyNamespace' "—其中 MyNamespace 是 Windows 執行階段元件命名空間的名稱。In a C++/WinRT app, when consuming a C# Windows Runtime component that uses XAML, the compiler produces an error of the form "'MyNamespace_XamlTypeInfo': is not a member of 'winrt::MyNamespace'"—where MyNamespace is the name of the Windows Runtime component's namespace. 在取用 C++/WinRT 應用程式的 pch.h 中,視適當情況新增 #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>—取代 MyNamespaceIn pch.h in the consuming C++/WinRT app, add #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>—replacing MyNamespace as appropriate.