Componentes de Windows Runtime con C++/WinRTWindows Runtime components with C++/WinRT

En este tema se muestra cómo usar C++/WinRT para crear y utilizar un componente de Windows Runtime — un componente al que se puede llamar desde una aplicación universal de Windows compilada con cualquier lenguaje de Windows Runtime.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.

Hay varias razones para compilar un componente de Windows Runtime en C++/WinRT.There are several reasons for building a Windows Runtime component in C++/WinRT.

  • Para disfrutar de las ventajas de rendimiento de C++ en operaciones complejas o de cálculo intensivo.To enjoy the performance advantage of C++ in complex or computationally intensive operations.
  • Para reutilizar el código de C++ estándar que ya está escrito y probado.To reuse standard C++ code that's already written and tested.
  • Para exponer la funcionalidad de Win32 en una aplicación Plataforma universal de Windows (UWP) escrita en, por ejemplo, C#.To expose Win32 functionality to a Universal Windows Platform (UWP) app written in, for example, C#.

En general, cuando se crea el componente/WinRT de C++, se pueden usar los tipos de la biblioteca estándar de C++ y los tipos integrados, excepto en el límite de la interfaz binaria de aplicación (ABI), donde se pasan los datos hacia y desde el código de otro .winmd paquete.In 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. En la ABI, use tipos de Windows Runtime.At the ABI, use Windows Runtime types. Además, en el código de C++/WinRT, use tipos como Delegate y Event para implementar eventos que se puedan generar desde su componente y que se controlen en otro lenguaje.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. Vea c++/WinRT para obtener más información acerca de c++/WinRT.See C++/WinRT for more info about C++/WinRT.

En el resto de este tema se explica cómo crear un componente de Windows Runtime en C++/WinRT y, a continuación, cómo consumirlo desde una aplicación.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.

El Windows Runtime componente que se va a crear en este tema contiene una clase en tiempo de ejecución que representa un termómetro.The Windows Runtime component that you'll build in this topic contains a runtime class representing a thermometer. En el tema también se muestra una aplicación principal que utiliza la clase en tiempo de ejecución del termómetro y llama a una función para ajustar la temperatura.The topic also demonstrates a Core App that consumes the thermometer runtime class, and calls a function to adjust the temperature.

Nota

Para más información sobre cómo instalar y usar C++/WinRT Visual Studio Extension (VSIX) y el paquete de NuGet (que juntos proporcionan la plantilla de proyecto y compatibilidad de la compilación), consulta Compatibilidad de Visual Studio para C++/WinRT.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.

Importante

Para conocer los conceptos y términos esenciales que te ayuden a entender cómo consumir y crear clases en tiempo de ejecución con C++/WinRT, consulta Consumir API con C++/WinRT y Crear API con C++/WinRT .For 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.

Crear un componente de Windows Runtime (ThermometerWRC)Create a Windows Runtime component (ThermometerWRC)

Para empezar, crea un proyecto en Microsoft Visual Studio.Begin by creating a new project in Microsoft Visual Studio. Cree un proyecto de componente de Windows Runtime (C++/WinRT) y asígnele el nombre ThermometerWRC (para "componente Windows Runtime termómetro").Create a Windows Runtime Component (C++/WinRT) project, and name it ThermometerWRC (for "thermometer Windows Runtime component"). Asegúrese de que la opción Colocar la solución y el proyecto en el mismo directorio esté desactivada.Make sure that Place solution and project in the same directory is unchecked. Elija como destino la versión más reciente disponible de manera general (es decir, no en versión preliminar) de Windows SDK.Target the latest generally-available (that is, not preview) version of the Windows SDK. El nombre del proyecto ThermometerWRC le proporcionará la experiencia más sencilla con el resto de los pasos de este tema.Naming the project ThermometerWRC will give you the easiest experience with the rest of the steps in this topic.

No compile aún el proyecto.Don't build the project yet.

El proyecto recién creado contiene un archivo llamado Class.idl.The newly-created project contains a file named Class.idl. En el Explorador de soluciones, cambie el nombre del archivo Thermometer.idl (al cambiar el nombre del archivo .idl, se cambia automáticamente el nombre de los archivos .h y .cpp dependientes).In Solution Explorer, rename that file Thermometer.idl (renaming the .idl file automatically renames the dependent .h and .cpp files, too). Reemplaza el contenido de Thermometer.idl por la lista siguiente.Replace the contents of Thermometer.idl with the listing below.

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

Guarde el archivo.Save the file. El proyecto no se compilará hasta su finalización en ese momento, pero crear ahora es algo útil porque genera los archivos de código fuente en los que se implementará la clase en tiempo de ejecución de termómetro .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. Así que puedes compilar ahora. En esta fase, verás errores de compilación porque no se han encontrado Class.h y Class.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).

Durante el proceso de compilación, la herramienta midl.exe se ejecuta para crear el archivo de metadatos de Windows Runtime de tu componente, que es \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). Después se ejecutará la herramienta cppwinrt.exe (con la opción -component) para generar archivos de código fuente y ayudarte a crear tu componente.Then, the cppwinrt.exe tool is run (with the -component option) to generate source code files to support you in authoring your component. Estos archivos incluyen códigos auxiliares para empezar a implementar la clase de tiempo de ejecución de termómetro que declaró en el IDL.These files include stubs to get you started implementing the Thermometer runtime class that you declared in your IDL. Estos archivos de código auxiliar son \ThermometerWRC\ThermometerWRC\Generated Files\sources\Thermometer.h y Thermometer.cpp.Those stubs are \ThermometerWRC\ThermometerWRC\Generated Files\sources\Thermometer.h and Thermometer.cpp.

Haz clic con el botón derecho en el nodo del proyecto y haz clic en Abrir carpeta en el Explorador de archivos.Right-click the project node and click Open Folder in File Explorer. Se abre la carpeta del proyecto en el Explorador de archivos.This opens the project folder in File Explorer. Allí, copia los archivos de código auxiliar Thermometer.h y Thermometer.cpp desde la carpeta \ThermometerWRC\ThermometerWRC\Generated Files\sources\ en la carpeta que contiene los archivos de proyecto, que es \ThermometerWRC\ThermometerWRC\, y reemplaza los archivos que hay en el destino.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. Ahora, vamos a abrir Thermometer.h y Thermometer.cpp e implementar nuestra clase en tiempo de ejecución.Now, let's open Thermometer.h and Thermometer.cpp and implement our runtime class. En Thermometer.h , agregue un nuevo miembro privado a la implementación (no a la implementación de fábrica) del termómetro.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 };
    };
}
...

En Thermometer.cpp , implemente el método AdjustTemperature como se muestra en la lista siguiente.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;
    }
}

También deberá eliminar el elemento static_assert de ambos archivos.You'll also need to delete the static_assert from both files.

Si las advertencias te impiden compilar, resuélvelas o establece la propiedad de proyecto C/C++ > General > Tratar advertencias como errores en No (/WX-) y vuelve a compilar el proyecto.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.

Creación de una aplicación principal (ThermometerCoreApp) para probar el componente Windows RuntimeCreate a Core App (ThermometerCoreApp) to test the Windows Runtime component

Ahora cree un nuevo proyecto (ya sea en la solución ThermometerWRC o en uno nuevo).Now create a new project (either in your ThermometerWRC solution, or in a new one). Cree un proyecto de aplicación principal (C++/WinRT) y asígnele el nombre ThermometerCoreApp.Create a Core App (C++/WinRT) project, and name it ThermometerCoreApp. Establezca ThermometerCoreApp como el proyecto de inicio si los dos proyectos están en la misma solución.Set ThermometerCoreApp as the startup project if the two projects are in the same solution.

Nota

Como se mencionó anteriormente, el archivo de metadatos de Windows Runtime para el componente Windows Runtime (cuyo proyecto llamado ThermometerWRC) se crea en la carpeta \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\. El primer segmento de esa ruta de acceso es el nombre de la carpeta que contiene el archivo de solución; el siguiente segmento es el subdirectorio de la que se denomina Debug; y el último segmento es el subdirectorio de la asignada para el componente de Windows Runtime.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. Si no ha indicado el nombre del proyecto ThermometerWRC, el archivo de metadatos estará en la carpeta \<YourProjectName>\Debug\<YourProjectName>\ .If you didn't name your project ThermometerWRC, then your metadata file will be in the folder \<YourProjectName>\Debug\<YourProjectName>\.

Ahora, en el proyecto de aplicación principal (ThermometerCoreApp), agregue una referencia y busque \ThermometerWRC\Debug\ThermometerWRC\ThermometerWRC.winmd (o agregue una referencia de proyecto a proyecto, si los dos proyectos están en la misma solución).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). Haz clic en Agregar y después en Aceptar.Click Add, and then OK. Ahora compile ThermometerCoreApp.Now build ThermometerCoreApp. En el caso improbable de que vea un error que no existe el archivo de carga readme.txt , excluya el archivo del proyecto de componente de Windows Runtime, vuelva a compilarlo y, a continuación, vuelva a generar ThermometerCoreApp.In 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.

Durante el proceso de compilación, la herramienta cppwinrt.exe se ejecutará para procesar el archivo .winmd al que se hace referencia en los archivos de código fuente que contienen tipos proyectados para ayudarte a consumir tu componente.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. El encabezado de los tipos proyectados para las clases en tiempo de ejecución de tu componente—denominado ThermometerWRC.h—se genera en la carpeta \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\.

Incluye dicho encabezado en App.cpp.Include that header in App.cpp.

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

También en App.cpp , agregue el código siguiente para crear una instancia de un objeto de termómetro (mediante el constructor predeterminado del tipo proyectado) y llamar a un método en el objeto de termómetro.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);
        ...
    }
    ...
};

Cada vez que se hace clic en la ventana, se incrementa la temperatura del objeto de termómetro.Each time you click the window, you increment the thermometer object's temperature. Puede establecer puntos de interrupción Si desea recorrer el código para confirmar que la aplicación realmente está llamando al componente de Windows Runtime.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.

Pasos siguientesNext steps

Para agregar más funcionalidad, o nuevos tipos de Windows Runtime, al componente Windows Runtime de C++/WinRT, puede seguir los mismos patrones mostrados anteriormente.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. En primer lugar, use IDL para definir la funcionalidad que desea exponer.First, use IDL to define the functionality you want to expose. A continuación, compile el proyecto en Visual Studio para generar una implementación de código auxiliar.Then build the project in Visual Studio to generate a stub implementation. Y, a continuación, complete la implementación según corresponda.And then complete the implementation as appropriate. Los métodos, las propiedades y los eventos que se definen en IDL son visibles para la aplicación que utiliza el componente de Windows Runtime.Any methods, properties, and events that you define in IDL are visible to the application that consumes your Windows Runtime Component. Para obtener más información acerca de IDL, vea Introducción a Lenguaje de definición de interfaz de Microsoft 3,0.For more info about IDL, see Introduction to Microsoft Interface Definition Language 3.0.

Para obtener un ejemplo de cómo agregar un evento a su componente de Windows Runtime, vea crear eventos en C++/WinRT.For an example of how to add an event to your Windows Runtime Component, see Author events in C++/WinRT.

Solución de problemasTroubleshooting

SíntomaSymptom SoluciónRemedy
En una aplicación de C++ o WinRT, al consumir un componente de Windows Runtime para C# que usa XAML, el compilador genera un error con el formato " 'MyNamespace_XamlTypeInfo': no es miembro de 'winrt::MyNamespace' "— donde MyNamespace es el nombre del espacio de nombres del componente de Windows Runtime.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. En el archivo pch.h de la aplicación que consume C++ o WinRT, agregue #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>— reemplace MyNamespace según corresponda.In pch.h in the consuming C++/WinRT app, add #include <winrt/MyNamespace.MyNamespace_XamlTypeInfo.h>—replacing MyNamespace as appropriate.