Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some clarifications around C++/CLI projects #39228

Merged
merged 3 commits into from
Jan 24, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 46 additions & 41 deletions docs/core/porting/cpp-cli.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
---
title: Migrate C++/CLI projects to .NET Core and .NET 5+
description: Learn about porting C++/CLI projects to .NET Core and .NET 5 and later versions.
title: Migrate C++/CLI projects to .NET
description: Learn about porting C++/CLI projects to .NET.
author: mjrousos
ms.date: 10/27/2023
ms.date: 01/23/2024
---

# How to port a C++/CLI project to .NET Core or .NET 5+
# How to port a C++/CLI project to .NET

Beginning with .NET Core 3.1 and Visual Studio 2019, [C++/CLI projects](/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp) can target .NET Core. This support makes it possible to port Windows desktop applications with C++/CLI interop layers to .NET Core/.NET 5+. This article describes how to port C++/CLI projects from .NET Framework to .NET Core 3.1.
Beginning with Visual Studio 2019, [C++/CLI projects](/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp) can target .NET. This support makes it possible to port Windows desktop applications with C++/CLI interop layers to .NET. This article describes how to port C++/CLI projects from .NET Framework to .NET.
adegeo marked this conversation as resolved.
Show resolved Hide resolved

## C++/CLI .NET Core limitations

There are some important limitations to porting C++/CLI projects to .NET Core compared to other languages:
There are some important with C++/CLI projects and .NET compared to .NET Framework:
adegeo marked this conversation as resolved.
Show resolved Hide resolved

- C++/CLI support for .NET Core is Windows only.
- C++/CLI projects can't target .NET Standard, only .NET Core or .NET Framework.
- C++/CLI projects don't support the new SDK-style project file format. Instead, even when targeting .NET Core, C++/CLI projects use the existing *.vcxproj* file format.
- C++/CLI projects can't multitarget multiple .NET platforms. If you need to build a C++/CLI project for both .NET Framework and .NET Core, use separate project files.
- .NET Core doesn't support `-clr:pure` or `-clr:safe` compilation, only the new `-clr:netcore` option (which is equivalent to `-clr` for .NET Framework).
- C++/CLI support for .NET is Windows only.
- C++/CLI projects can't target .NET Standard.
- C++/CLI projects don't support the new SDK-style project file format. Instead, C++/CLI projects use the existing _.vcxproj_ file format.
adegeo marked this conversation as resolved.
Show resolved Hide resolved
- C++/CLI projects can't target multiple .NET platforms. If you need to build a C++/CLI project for both .NET and .NET Framework.
adegeo marked this conversation as resolved.
Show resolved Hide resolved
- .NET doesn't support `-clr:pure` or `-clr:safe` compilation, only the new `-clr:netcore` option (which is equivalent to `-clr` for .NET Framework).
adegeo marked this conversation as resolved.
Show resolved Hide resolved
- Compiling a C++/CLI project to an executable isn't supported. You must compile to a DLL.

## Port a C++/CLI project

To port a C++/CLI project to .NET Core, make the following changes to the *.vcxproj* file. These migration steps differ from the steps needed for other project types because C++/CLI projects don't use SDK-style project files.
To port a C++/CLI project to .NET, make the following changes to the _.vcxproj_ file. These migration steps differ from the steps needed for other project types because C++/CLI projects don't use SDK-style project files.

1. Replace `<CLRSupport>true</CLRSupport>` properties with `<CLRSupport>NetCore</CLRSupport>`. This property is often in configuration-specific property groups, so you might need to replace it in multiple places.
2. Replace `<TargetFrameworkVersion>` properties with `<TargetFramework>netcoreapp3.1</TargetFramework>`. Be sure to change the tag as well as the value.
3. Remove any .NET Framework references to `System`, `System.Data`, `System.Windows.Forms`, and `System.Xml`, like `<Reference Include="System" />`. .NET Core SDK assemblies are automatically referenced when using `<CLRSupport>NetCore</CLRSupport>`.
4. Update API usage in *.cpp* files, as necessary, to remove APIs unavailable to .NET Core. Because C++/CLI projects tend to be fairly thin interop layers, there are often not many changes needed. You can use the [.NET Portability Analyzer](../../standard/analyzers/portability-analyzer.md) to identify unsupported .NET APIs used by C++/CLI binaries just as with purely managed binaries.
01. Replace `<CLRSupport>true</CLRSupport>` properties with `<CLRSupport>NetCore</CLRSupport>`. This property is often in configuration-specific property groups, so you might need to replace it in multiple places.
01. Replace `<TargetFrameworkVersion>` properties with `<TargetFramework>net8.0</TargetFramework>`. Be sure to change the tag and value.
01. Remove any .NET Framework references to `System`, `System.Data`, `System.Windows.Forms`, and `System.Xml`, like `<Reference Include="System" />`. .NET SDK assemblies are automatically referenced when using `<CLRSupport>NetCore</CLRSupport>`.
01. Update API usage in _.cpp_ files, as necessary, to remove APIs unavailable to .NET. Because C++/CLI projects tend to be fairly thin interop layers, there are often not many changes needed. You can use the [.NET Portability Analyzer](../../standard/analyzers/portability-analyzer.md) to identify unsupported .NET APIs used by C++/CLI binaries.
01. If your project was an executable, perform the following steps:
01. Change the project type to a library.
01. Create a new .NET executable project.
01. In the .NET executable project, add reference the C++/CLI .NET library.

### WPF and Windows Forms usage

.NET Core C++/CLI projects can use Windows Forms and WPF APIs. To use these Windows desktop APIs, you need to add explicit framework references to the UI libraries. SDK-style projects that use Windows desktop APIs reference the necessary framework libraries automatically by using the `Microsoft.NET.Sdk.WindowsDesktop` SDK. Because C++/CLI projects don't use the SDK-style project format, they need to add explicit framework references when targeting .NET Core.
.NET C++/CLI projects can use Windows Forms and WPF APIs. To use these Windows desktop APIs, you need to add explicit framework references to the UI libraries. SDK-style projects that use Windows desktop APIs reference the necessary framework libraries automatically by using the `Microsoft.NET.Sdk.WindowsDesktop` SDK. Because C++/CLI projects don't use the SDK-style project format, they need to add explicit framework references when targeting .NET Core.

To use Windows Forms APIs, add this reference to the *.vcxproj* file:
To use Windows Forms APIs, add this reference to the _.vcxproj_ file:

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

To use WPF APIs, add this reference to the *.vcxproj* file:
To use WPF APIs, add this reference to the _.vcxproj_ file:

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

To use both Windows Forms and WPF APIs, add this reference to the *.vcxproj* file:
To use both Windows Forms and WPF APIs, add this reference to the _.vcxproj_ file:

```xml
<!-- Reference the entirety of the Windows desktop framework:
Expand All @@ -58,27 +63,27 @@ Currently, it's not possible to add these references by using Visual Studio's re

## Build without MSBuild

It's also possible to build C++/CLI projects without using MSBuild. Follow these steps to build a C++/CLI project for .NET Core directly with *cl.exe* and *link.exe*:

1. When compiling, pass `-clr:netcore` to *cl.exe*.
2. Reference necessary .NET Core reference assemblies.
3. When linking, provide the .NET Core app host directory as a `LibPath`, so that *ijwhost.lib* can be found.
4. Copy *ijwhost.dll* from the .NET Core app host directory to the project's output directory.
5. Make sure a [runtimeconfig.json](https://github.com/dotnet/sdk/blob/main/documentation/specs/runtime-configuration-file.md) file exists for the first component of the application that will run managed code. For latest versions of Visual Studio, a *runtime.config* file is created and copied automatically.

For older versions of Visual Studio, if the application has a native entry point, you need to manually create the following *runtimeconfig.json* file for the first C++/CLI library to use the .NET Core runtime. If a C++/CLI library is called from a managed entry point, the library doesn't need a *runtimeconfig.json* file, because the entry point assembly has one that's used when starting the runtime.

```json
{
"runtimeOptions": {
"tfm": "netcoreapp3.1",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.1.0"
}
}
}
```
It's also possible to build C++/CLI projects without using MSBuild. Follow these steps to build a C++/CLI project for .NET Core directly with _cl.exe_ and _link.exe_:

01. When compiling, pass `-clr:netcore` to _cl.exe_.
01. Reference necessary .NET reference assemblies.
01. When linking, provide the .NET app host directory as a `LibPath`, so that _ijwhost.lib_ can be found.
01. Copy _ijwhost.dll_ from the .NET app host directory to the project's output directory.
01. Make sure a [_runtimeconfig.json_](https://github.com/dotnet/sdk/blob/main/documentation/specs/runtime-configuration-file.md) file exists for the first component of the application that runs managed code. For latest versions of Visual Studio, a _runtime.config_ file is created and copied automatically.

For older versions of Visual Studio, if the application has a native entry point, you need to manually create the following _runtimeconfig.json_ file for the first C++/CLI library to use the .NET runtime. If a C++/CLI library is called from a managed entry point, the library doesn't need a _runtimeconfig.json_ file, because the entry point assembly has one that is used when starting the runtime.

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

> [!NOTE]
> C++/CLI assemblies that target .NET 7 or a later version are always loaded into the default <xref:System.Runtime.Loader.AssemblyLoadContext>. However, in .NET 6 and earlier versions, C++/CLI assemblies might be loaded multiple times, each time into a new `AssemblyLoadContext`. If the first time that managed code in a C++/CLI assembly is executed:
Expand Down
Loading