Compartir a través de


Cómo migrar un proyecto de C++/CLI a .NET

A partir de Visual Studio 2019, los proyectos de C++/CLI pueden tener como destino .NET. Esta compatibilidad permite migrar aplicaciones de escritorio de Windows con capas de interoperabilidad de C++/CLI de .NET Framework a .NET. En este artículo se describe cómo migrar proyectos de C++/CLI de .NET Framework a .NET.

Limitaciones de C++/CLI en .NET Core

Hay algunas limitaciones importantes con los proyectos de C++/CLI y .NET en comparación con .NET Framework:

  • No se admite la compilación de un proyecto de C++/CLI en un archivo ejecutable. Debe compilar a una DLL.
  • La compatibilidad con C++/CLI para .NET es solo para Windows.
  • Los proyectos de C++/CLI no pueden tener como destino .NET Standard.
  • Los proyectos de C++/CLI no admiten el formato de archivo de proyecto de estilo SDK más reciente. En su lugar, los proyectos de C++/CLI usan el mismo formato de archivo .vcxproj que usan otros proyectos de Visual Studio C++.
  • Los proyectos de C++/CLI no pueden tener como destino varias plataformas .NET. Si necesita compilar un proyecto de C++/CLI para .NET y .NET Framework, use archivos de proyecto independientes.
  • .NET no admite -clr:pure ni -clr:safe compilación, sólo la opción más reciente, -clr:netcore (que es equivalente a -clr para .NET Framework).

Migrar un proyecto de C++/CLI

Para migrar un proyecto de C++/CLI a .NET, realice los siguientes cambios en el archivo .vcxproj . Estos pasos de migración difieren de los pasos necesarios para otros tipos de proyecto porque los proyectos de C++/CLI no usan archivos de proyecto de estilo SDK.

  1. Reemplace las <CLRSupport>true</CLRSupport> propiedades por <CLRSupport>NetCore</CLRSupport>. Esta propiedad suele estar en grupos de propiedades específicas de la configuración, por lo que puede que tenga que reemplazarla en varios lugares.
  2. Reemplace las <TargetFrameworkVersion> propiedades por <TargetFramework>net8.0</TargetFramework>. Asegúrese de cambiar la etiqueta y el valor.
  3. Quite las referencias de .NET Framework a System, System.Data, System.Windows.Formsy System.Xml, como <Reference Include="System" />. Se hace referencia automáticamente a los ensamblados del SDK de .NET al usar <CLRSupport>NetCore</CLRSupport>.
  4. Actualice el uso de la API en .cpp archivos, según sea necesario, para quitar las API no disponibles para .NET. Dado que los proyectos de C++/CLI tienden a ser capas de interoperabilidad bastante delgadas, a menudo no se necesitan muchos cambios. Puede usar el Analizador de portabilidad de .NET para identificar las API de .NET no admitidas que usan los archivos binarios de C++/CLI.
  5. Si el proyecto era un ejecutable, realice los pasos siguientes:
    1. Cambie el tipo de proyecto a una biblioteca.
    2. Cree un nuevo proyecto ejecutable de .NET.
    3. En el proyecto ejecutable de .NET, agregue una referencia a la biblioteca .NET de C++/CLI.

Uso de WPF y Windows Forms

Los proyectos de .NET C++/CLI pueden usar las API de Windows Forms y WPF. Para usar estas API de escritorio de Windows, debe agregar referencias de marco explícitas a las bibliotecas de interfaz de usuario. Los proyectos de estilo SDK que usan las API de escritorio de Windows hacen referencia a las bibliotecas de marcos necesarias automáticamente mediante el Microsoft.NET.Sdk.WindowsDesktop SDK. Dado que los proyectos de C++/CLI no usan el formato de proyecto de estilo SDK, deben agregar referencias de marco explícitas al tener como destino .NET Core.

Para usar las API de Windows Forms, agregue esta referencia al archivo .vcxproj :

<!-- Reference all of Windows Forms -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />

Para usar las API de WPF, agregue esta referencia al archivo .vcxproj :

<!-- Reference all of WPF -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />

Para usar las API de Windows Forms y WPF, agregue esta referencia al archivo .vcxproj :

<!-- Reference the entirety of the Windows desktop framework:
     Windows Forms, WPF, and the types that provide integration between them -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />

Actualmente, no es posible agregar estas referencias mediante el administrador de referencias de Visual Studio. En su lugar, actualice el archivo del proyecto editándolo manualmente. En Visual Studio, primero debe descargar el proyecto. También puede usar otro editor como Visual Studio Code.

Compilación sin MSBuild

También es posible compilar proyectos de C++/CLI sin usar MSBuild. Siga estos pasos para compilar un proyecto de C++/CLI para .NET Core directamente con cl.exe y link.exe:

  1. Al compilar, pase -clr:netcore a cl.exe.

  2. Haga referencia a los ensamblados de referencia de .NET necesarios.

  3. Al vincular, proporcione el directorio host de la aplicación .NET como , LibPathpara que se pueda encontrar ijwhost.lib .

  4. Copie ijwhost.dll del directorio host de la aplicación .NET en el directorio de salida del proyecto.

  5. Asegúrese de que existe un archivo runtimeconfig.json para el primer componente de la aplicación que ejecuta código administrado. Para las versiones más recientes de Visual Studio, se crea y copia automáticamente un archivo runtime.config .

    Para versiones anteriores de Visual Studio, si la aplicación tiene un punto de entrada nativo, debe crear manualmente el siguiente archivo runtimeconfig.json para la primera biblioteca de C++/CLI para usar el entorno de ejecución de .NET. Si se llama a una biblioteca de C++/CLI desde un punto de entrada administrado, la biblioteca no necesita un archivo runtimeconfig.json , ya que el ensamblado del punto de entrada tiene uno que se usa al iniciar el tiempo de ejecución.

    {
       "runtimeOptions": {
          "tfm": "net8.0",
          "framework": {
          "name": "Microsoft.NETCore.App",
          "version": "8.0.0"
          }
       }
    }
    

Nota:

Los ensamblados de C++/CLI que tienen como destino .NET 7 o una versión posterior siempre se cargan en el valor predeterminado AssemblyLoadContext. Sin embargo, en .NET 6 y versiones anteriores, los ensamblados de C++/CLI se pueden cargar varias veces, cada vez en un nuevo AssemblyLoadContext. Si la primera vez que se ejecuta el código administrado en un ensamblado de C++/CLI:

  • Es desde un autor de llamada nativo, el ensamblado se carga en un AssemblyLoadContext independiente.
  • Es desde un autor de llamada administrado, el ensamblado se carga en el mismo AssemblyLoadContext que el autor de la llamada (por lo general, el valor predeterminado).

Para cargar siempre el ensamblado de C++/CLI en el AssemblyLoadContext predeterminado, puede agregar una llamada de estilo "initialize" desde el ensamblado de punto de entrada al ensamblado de C++/CLI. Para más información, consulte este problema de dotnet/runtime.