diff --git a/docs/core/tutorials/netcore-hosting.md b/docs/core/tutorials/netcore-hosting.md
index da8b3d7e85f09..32942fe9144a4 100644
--- a/docs/core/tutorials/netcore-hosting.md
+++ b/docs/core/tutorials/netcore-hosting.md
@@ -1,56 +1,53 @@
---
-title: Write a custom .NET Core runtime host
-description: Learn to host the .NET Core runtime from native code to support advanced scenarios that require controlling how the .NET Core runtime works.
+title: Write a custom .NET runtime host
+description: Learn to host the .NET runtime from native code to support advanced scenarios that require controlling how the .NET runtime works.
author: mjrousos
ms.topic: how-to
ms.date: 12/21/2018
---
-# Write a custom .NET Core host to control the .NET runtime from your native code
+# Write a custom .NET host to control the .NET runtime from your native code
-Like all managed code, .NET Core applications are executed by a host. The host is responsible for starting the runtime (including components like the JIT and garbage collector) and invoking managed entry points.
+Like all managed code, .NET applications are executed by a host. The host is responsible for starting the runtime (including components like the JIT and garbage collector) and invoking managed entry points.
-Hosting the .NET Core runtime is an advanced scenario and, in most cases, .NET Core developers don't need to worry about hosting because .NET Core build processes provide a default host to run .NET Core applications. In some specialized circumstances, though, it can be useful to explicitly host the .NET Core runtime, either as a means of invoking managed code in a native process or in order to gain more control over how the runtime works.
+Hosting the .NET runtime is an advanced scenario and, in most cases, .NET developers don't need to worry about hosting because .NET build processes provide a default host to run .NET applications. In some specialized circumstances, though, it can be useful to explicitly host the .NET runtime, either as a means of invoking managed code in a native process or in order to gain more control over how the runtime works.
-This article gives an overview of the steps necessary to start the .NET Core runtime from native code and execute managed code in it.
+This article gives an overview of the steps necessary to start the .NET runtime from native code and execute managed code in it.
## Prerequisites
-Because hosts are native applications, this tutorial covers constructing a C++ application to host .NET Core. You will need a C++ development environment (such as that provided by [Visual Studio](https://aka.ms/vsdownload?utm_source=mscom&utm_campaign=msdocs)).
+Because hosts are native applications, this tutorial covers constructing a C++ application to host .NET. You will need a C++ development environment (such as that provided by [Visual Studio](https://aka.ms/vsdownload?utm_source=mscom&utm_campaign=msdocs)).
-You will also want a simple .NET Core application to test the host with, so you should install the [.NET Core SDK](https://dotnet.microsoft.com/download) and [build a small .NET Core test app](with-visual-studio.md) (such as a 'Hello World' app). The 'Hello World' app created by the new .NET Core console project template is sufficient.
+You will also need to build a .NET component to test the host with, so you should install the [.NET SDK](https://dotnet.microsoft.com/download).
## Hosting APIs
-There are two different APIs that can be used to host .NET Core. This article (and its associated [samples](https://github.com/dotnet/samples/tree/main/core/hosting)) covers these 2 options.
+Hosting the .NET runtime in .NET Core 3.0 and above is done with the `nethost` and `hostfxr` libraries' APIs. These entry points handle the complexity of finding and setting up the runtime for initialization and allow both launching a managed application and calling into a static managed method.
-* The preferred method of hosting the .NET Core runtime in .NET Core 3.0 and above is with the `nethost` and `hostfxr` libraries' APIs. These entry points handle the complexity of finding and setting up the runtime for initialization and allow both launching a managed application and calling into a static managed method.
-* The preferred method of hosting the .NET Core runtime prior to .NET Core 3.0 is with the [`coreclrhost.h`](https://github.com/dotnet/runtime/blob/main/src/coreclr/hosts/inc/coreclrhost.h) API. This API exposes functions for easily starting and stopping the runtime and invoking managed code (either by launching a managed exe or by calling static managed methods).
+Prior to .NET Core 3.0, the only option for hosting the runtime was through the [`coreclrhost.h`](https://github.com/dotnet/runtime/blob/main/src/coreclr/hosts/inc/coreclrhost.h) API. This hosting API is obsolete now and should not be used for hosting .NET Core 3.0 and higher runtimes.
-## Sample Hosts
-
-[Sample hosts](https://github.com/dotnet/samples/tree/main/core/hosting) demonstrating the steps outlined in the tutorials below are available in the dotnet/samples GitHub repository. Comments in the samples clearly associate the numbered steps from these tutorials with where they're performed in the sample. For download instructions, see [Samples and Tutorials](../../samples-and-tutorials/index.md#view-and-download-samples).
+## Create a host using `nethost.h` and `hostfxr.h`
-Keep in mind that the sample hosts are meant to be used for learning purposes, so they are light on error checking and are designed to emphasize readability over efficiency.
+A [sample host](https://github.com/dotnet/samples/tree/main/core/hosting) demonstrating the steps outlined in the tutorial below is available in the dotnet/samples GitHub repository. Comments in the sample clearly associate the numbered steps from this tutorial with where they're performed in the sample. For download instructions, see [Samples and Tutorials](../../samples-and-tutorials/index.md#view-and-download-samples).
-## Create a host using `nethost.h` and `hostfxr.h`
+Keep in mind that the sample host is meant to be used for learning purposes, so it is light on error checking and designed to emphasize readability over efficiency.
-The following steps detail how to use the `nethost` and `hostfxr` libraries to start the .NET Core runtime in a native application and call into a managed static method. The [sample](https://github.com/dotnet/samples/tree/main/core/hosting/HostWithHostFxr) uses the `nethost` header and library installed with the .NET SDK and copies of the [`coreclr_delegates.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/coreclr_delegates.h) and [`hostfxr.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h) files from the [dotnet/runtime](https://github.com/dotnet/runtime) repository.
+The following steps detail how to use the `nethost` and `hostfxr` libraries to start the .NET runtime in a native application and call into a managed static method. The [sample](https://github.com/dotnet/samples/tree/main/core/hosting/HostWithHostFxr) uses the `nethost` header and library installed with the .NET SDK and copies of the [`coreclr_delegates.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/coreclr_delegates.h) and [`hostfxr.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h) files from the [dotnet/runtime](https://github.com/dotnet/runtime) repository.
### Step 1 - Load `hostfxr` and get exported hosting functions
-The `nethost` library provides the `get_hostfxr_path` function for locating the `hostfxr` library. The `hostfxr` library exposes functions for hosting the .NET Core runtime. The full list of functions can be found in [`hostfxr.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h) and the [native hosting design document](https://github.com/dotnet/runtime/blob/main/docs/design/features/native-hosting.md). The sample and this tutorial use the following:
+The `nethost` library provides the `get_hostfxr_path` function for locating the `hostfxr` library. The `hostfxr` library exposes functions for hosting the .NET runtime. The full list of functions can be found in [`hostfxr.h`](https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h) and the [native hosting design document](https://github.com/dotnet/runtime/blob/main/docs/design/features/native-hosting.md). The sample and this tutorial use the following:
-* `hostfxr_initialize_for_runtime_config`: Initializes a host context and prepares for initialization of the .NET Core runtime using the specified runtime configuration.
+* `hostfxr_initialize_for_runtime_config`: Initializes a host context and prepares for initialization of the .NET runtime using the specified runtime configuration.
* `hostfxr_get_runtime_delegate`: Gets a delegate for runtime functionality.
* `hostfxr_close`: Closes a host context.
-The `hostfxr` library is found using `get_hostfxr_path`. It is then loaded and its exports are retrieved.
+The `hostfxr` library is found using `get_hostfxr_path` API from `nethost` library. It is then loaded and its exports are retrieved.
[!code-cpp[HostFxrHost#LoadHostFxr](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp#LoadHostFxr)]
-### Step 2 - Initialize and start the .NET Core runtime
+### Step 2 - Initialize and start the .NET runtime
-The `hostfxr_initialize_for_runtime_config` and `hostfxr_get_runtime_delegate` functions initialize and start the .NET Core runtime using the runtime configuration for the managed component that will be loaded. The `hostfxr_get_runtime_delegate` function is used to get a runtime delegate that allows loading a managed assembly and getting a function pointer to a static method in that assembly.
+The `hostfxr_initialize_for_runtime_config` and `hostfxr_get_runtime_delegate` functions initialize and start the .NET runtime using the runtime configuration for the managed component that will be loaded. The `hostfxr_get_runtime_delegate` function is used to get a runtime delegate that allows loading a managed assembly and getting a function pointer to a static method in that assembly.
[!code-cpp[HostFxrHost#Initialize](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp#Initialize)]
@@ -73,96 +70,3 @@ A different signature can be used by specifying the delegate type name when call
The native host can now call the managed method and pass it the desired parameters.
[!code-cpp[HostFxrHost#CallManaged](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp#CallManaged)]
-
-## Create a host using `coreclrhost.h`
-
-The following steps detail how to use the `coreclrhost.h` API to start the .NET Core runtime in a native application and call into a managed static method. The code snippets in this document use some Windows-specific APIs, but the [full sample host](https://github.com/dotnet/samples/tree/main/core/hosting/HostWithCoreClrHost) shows both Windows and Linux code paths.
-
-The [corerun host](https://github.com/dotnet/runtime/tree/main/src/coreclr/hosts/corerun) shows a more complex, real-world, cross-platform example of hosting using `coreclrhost.h`.
-
-### Step 1 - Find and load CoreCLR
-
-The .NET Core runtime APIs are in *coreclr.dll* (on Windows), in *libcoreclr.so* (on Linux), or in *libcoreclr.dylib* (on macOS). The first step to hosting .NET Core is to load the CoreCLR library. Some hosts probe different paths or use input parameters to find the library while others know to load it from a certain path (next to the host, for example, or from a machine-wide location).
-
-Once found, the library is loaded with `LoadLibraryEx` (on Windows) or `dlopen` (on Linux/macOS).
-
-[!code-cpp[CoreClrHost#1](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#1)]
-
-### Step 2 - Get .NET Core hosting functions
-
-CoreClrHost has several important methods useful for hosting .NET Core:
-
-* `coreclr_initialize`: Starts the .NET Core runtime and sets up the default (and only) AppDomain.
-* `coreclr_execute_assembly`: Executes a managed assembly.
-* `coreclr_create_delegate`: Creates a function pointer to a managed method.
-* `coreclr_shutdown`: Shuts down the .NET Core runtime.
-* `coreclr_shutdown_2`: Like `coreclr_shutdown`, but also retrieves the managed code's exit code.
-
-After loading the CoreCLR library, the next step is to get references to these functions using `GetProcAddress` (on Windows) or `dlsym` (on Linux/macOS).
-
-[!code-cpp[CoreClrHost#2](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#2)]
-
-### Step 3 - Prepare runtime properties
-
-Before starting the runtime, it is necessary to prepare some properties to specify behavior (especially concerning the assembly loader).
-
-Common properties include:
-
-* `TRUSTED_PLATFORM_ASSEMBLIES`
- This is a list of assembly paths (delimited by ';' on Windows and ':' on Linux) which the runtime will be able to resolve by default. Some hosts have hard-coded manifests listing assemblies they can load. Others will put any library in certain locations (next to *coreclr.dll*, for example) on this list.
-* `APP_PATHS`
- This is a list of paths to probe in for an assembly if it can't be found in the trusted platform assemblies (TPA) list. Because the host has more control over which assemblies are loaded using the TPA list, it is a best practice for hosts to determine which assemblies they expect to load and list them explicitly. If probing at run time is needed, however, this property can enable that scenario.
-* `NATIVE_DLL_SEARCH_DIRECTORIES`
- This property is a list of paths the loader should probe when looking for native libraries called via p/invoke.
-* `PLATFORM_RESOURCE_ROOTS`
- This list includes paths to probe in for resource satellite assemblies (in culture-specific subdirectories).
-
-In this sample host, the TPA list is constructed by simply listing all libraries in the current directory:
-
-[!code-cpp[CoreClrHost#7](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#7)]
-
-Because the sample is simple, it only needs the `TRUSTED_PLATFORM_ASSEMBLIES` property:
-
-[!code-cpp[CoreClrHost#3](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#3)]
-
-### Step 4 - Start the runtime
-
-`coreclrhost.h` APIs start the runtime and create the default AppDomain all with a single call. The `coreclr_initialize` function takes a base path, name, and the properties described earlier and returns back a handle to the host via the `hostHandle` parameter.
-
-[!code-cpp[CoreClrHost#4](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#4)]
-
-### Step 5 - Run managed code!
-
-With the runtime started, the host can call managed code. This can be done in a couple of different ways. The sample code linked to this tutorial uses the `coreclr_create_delegate` function to create a delegate to a static managed method. This API takes the [assembly name](../../standard/assembly/names.md), namespace-qualified type name, and method name as inputs and returns a delegate that can be used to invoke the method.
-
-[!code-cpp[CoreClrHost#5](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#5)]
-
-In this sample, the host can now call `managedDelegate` to run the `ManagedWorker.DoWork` method.
-
-Alternatively, the `coreclr_execute_assembly` function can be used to launch a managed executable. This API takes an assembly path and array of arguments as input parameters. It loads the assembly at that path and invokes its main method.
-
-```c++
-int hr = executeAssembly(
- hostHandle,
- domainId,
- argumentCount,
- arguments,
- "HelloWorld.exe",
- (unsigned int*)&exitCode);
-```
-
-### Step 6 - Shutdown and clean up
-
-Finally, when the host is done running managed code, the .NET Core runtime is shut down with `coreclr_shutdown` or `coreclr_shutdown_2`.
-
-[!code-cpp[CoreClrHost#6](~/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp#6)]
-
-CoreCLR does not support reinitialization or unloading. Do not call `coreclr_initialize` again or unload the CoreCLR library.
-
-## Conclusion
-
-Once your host is built, it can be tested by running it from the command line and passing any arguments the host expects. When specifying the .NET Core app for the host to run, be sure to use the .dll that is produced by `dotnet build`. Executables (.exe files) produced by `dotnet publish` for self-contained applications are actually the default .NET Core host (so that the app can be launched directly from the command line in mainline scenarios); user code is compiled into a dll of the same name.
-
-If things don't work initially, double-check that *coreclr.dll* is available in the location expected by the host, that all necessary Framework libraries are in the TPA list, and that CoreCLR's bitness (32-bit or 64-bit) matches how the host was built.
-
-Hosting the .NET Core runtime is an advanced scenario that many developers won't require, but for those who need to launch managed code from a native process, or who need more control over the .NET Core runtime's behavior, it can be very useful.
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/README.md b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/README.md
deleted file mode 100644
index 9a5ae68e43fd9..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-.NET Core Hosting Sample
-========================
-
-This sample demonstrates a simple .NET Core host using the hosting APIs from [`coreclrhost.h`](https://github.com/dotnet/runtime/blob/main/src/coreclr/hosts/inc/coreclrhost.h). The sample host loads and starts the .NET runtime, loads managed code, calls into a managed method, and provides a function pointer for the managed code to call back into the host.
-
-This sample is part of the [.NET Core hosting tutorial](https://docs.microsoft.com/dotnet/core/tutorials/netcore-hosting). See that topic for a more detailed explanation of this sample.
-
-About .NET Core Hosts
----------------------
-
-.NET Core applications are always run by a host. In most cases, the default dotnet.exe host is used.
-
-It is possible to create your own host, though, to enable starting and running .NET Core code from a native application, or to enable a high degree of control over how the runtime operates. More complex, real-world hosts can be found in the [dotnet/runtime](https://github.com/dotnet/runtime/tree/main/src/coreclr/hosts) repository.
-
-Build and Run
--------------
-
-To build this sample, just use the included build scripts *build.bat*, *build.sh*, or *buildOsx.sh*. These scripts build both the managed target assembly (ManagedLibrary.dll) and the host (SampleHost.exe). The build scripts are just simple wrappers around two build calls (`dotnet publish` for the managed component of the sample and cl.exe/g++ for the host), so it's also easy to build the two components directly if you prefer. The build scripts build for Windows 10 (x64), Linux (x64), and OSX (x64), respectively, and assume that both the dotnet CLI and the C++ compiler (cl.exe or g++) are available on the path. On Windows, a [Developer Command Prompt for Visual Studio](https://docs.microsoft.com/cpp/build/building-on-the-command-line#developer_command_prompt_shortcuts) should be used. The build scripts will need modified if you intend to target other platforms or use tools from other paths. Be sure that the bitness of the host and sample app match. By default, the build scripts build ManagedLibrary.dll for x64, so you will need to build the host for 64-bit.
-
-To run the host, just execute SampleHost from the bin/{{OS}} directory.
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.bat b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.bat
deleted file mode 100644
index adf7f5e056b11..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.bat
+++ /dev/null
@@ -1,17 +0,0 @@
-@echo off
-
-REM This script builds the sample for x64 Windows 10. If using Win7, adjust the 'dotnet publish' command.
-REM It assumes that both the dotnet CLI and cl.exe compiler are available on the path.
-REM A Visual Studio Developer Command Prompt will already have cl.exe on its path.
-
-SET SRCDIR=%~dp0src
-SET OUTDIR=%~dp0bin\windows
-
-mkdir %OUTDIR%
-
-REM Build managed component
-echo Building Managed Library
-dotnet publish --self-contained -r win10-x64 %SRCDIR%\ManagedLibrary\ManagedLibrary.csproj -o %OUTDIR%
-
-REM Build native component
-cl.exe %SRCDIR%\SampleHost.cpp /Fo%OUTDIR%\ /Fd%OUTDIR%\SampleHost.pdb /EHsc /Od /GS /sdl /Zi /D "WINDOWS" /link ole32.lib /out:%OUTDIR%\SampleHost.exe
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.sh b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.sh
deleted file mode 100644
index d3c0042d62693..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/build.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-# This script builds the sample for x64 Linux.
-# It assumes that both the dotnet CLI and g++ compiler are available on the path.
-
-SCRIPTPATH=$(readlink -f "$0")
-BASEDIR=$(dirname $SCRIPTPATH)
-SRCDIR=${BASEDIR}/src
-OUTDIR=${BASEDIR}/bin/linux
-
-# Make output directory, if needed
-if [ ! -d "${OUTDIR}" ]; then
- mkdir -p ${OUTDIR}
-fi
-
-# Build managed component
-echo Building Managed Library
-dotnet publish --self-contained -r linux-x64 ${SRCDIR}/ManagedLibrary/ManagedLibrary.csproj -o ${OUTDIR}
-
-# Build native component
-g++ -o ${OUTDIR}/SampleHost -D LINUX ${SRCDIR}/SampleHost.cpp -ldl
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/buildOsx.sh b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/buildOsx.sh
deleted file mode 100644
index 5f15c1ff004d3..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/buildOsx.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-# This script builds the sample for x64 OSX.
-# It assumes that both the dotnet CLI and g++ compiler are available on the path.
-
-BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-SRCDIR=${BASEDIR}/src
-OUTDIR=${BASEDIR}/bin/osx
-
-# Make output directory, if needed
-if [ ! -d "${OUTDIR}" ]; then
- mkdir -p ${OUTDIR}
-fi
-
-# Build managed component
-echo Building Managed Library
-echo dotnet publish --self-contained -r osx-x64 ${SRCDIR}/ManagedLibrary/ManagedLibrary.csproj -o ${OUTDIR}
-dotnet publish --self-contained -r osx-x64 ${SRCDIR}/ManagedLibrary/ManagedLibrary.csproj -o ${OUTDIR}
-
-# Build native component
-# -D both LINUX and OSX since most LINUX code paths apply to OSX also
-g++ -o ${OUTDIR}/SampleHost -D LINUX -D OSX ${SRCDIR}/SampleHost.cpp -ldl
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedLibrary.csproj b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedLibrary.csproj
deleted file mode 100644
index ec386c10a2452..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedLibrary.csproj
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
- Exe
- netcoreapp3.1
-
-
-
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedWorker.cs b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedWorker.cs
deleted file mode 100644
index c7f6b69c8b60b..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/ManagedLibrary/ManagedWorker.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-namespace ManagedLibrary
-{
- // Sample managed code for the host to call
- public class ManagedWorker
- {
- // This assembly is being built as an exe as a simple way to
- // get .NET Core runtime libraries deployed (`dotnet publish` will
- // publish .NET Core libraries for exes). Therefore, this assembly
- // requires an entry point method even though it is unused.
- public static void Main()
- {
- Console.WriteLine("This assembly is not meant to be run directly.");
- Console.WriteLine("Instead, please use the SampleHost process to load this assembly.");
- }
-
- public delegate int ReportProgressFunction(int progress);
-
- // This test method doesn't actually do anything, it just takes some input parameters,
- // waits (in a loop) for a bit, invoking the callback function periodically, and
- // then returns a string version of the double[] passed in.
- [return: MarshalAs(UnmanagedType.LPStr)]
- public static string DoWork(
- [MarshalAs(UnmanagedType.LPStr)] string jobName,
- int iterations,
- int dataSize,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] double[] data,
- ReportProgressFunction reportProgressFunction)
- {
- for (int i = 1; i <= iterations; i++)
- {
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.WriteLine($"Beginning work iteration {i}");
- Console.ResetColor();
-
- // Pause as if doing work
- Thread.Sleep(1000);
-
- // Call the native callback and write its return value to the console
- var progressResponse = reportProgressFunction(i);
- Console.WriteLine($"Received response [{progressResponse}] from progress function");
- }
-
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine($"Work completed");
- Console.ResetColor();
-
- return $"Data received: {string.Join(", ", data.Select(d => d.ToString()))}";
- }
- }
-}
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp
deleted file mode 100644
index d39988028e067..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/SampleHost.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-#include
-#include
-#include
-#include
-
-// https://github.com/dotnet/coreclr/blob/master/src/coreclr/hosts/inc/coreclrhost.h
-#include "coreclrhost.h"
-
-#define MANAGED_ASSEMBLY "ManagedLibrary.dll"
-
-// Define OS-specific items like the CoreCLR library's name and path elements
-#if WINDOWS
-#include
-#define FS_SEPARATOR "\\"
-#define PATH_DELIMITER ";"
-#define CORECLR_FILE_NAME "coreclr.dll"
-#elif LINUX
-#include
-#include
-#include
-#define FS_SEPARATOR "/"
-#define PATH_DELIMITER ":"
-#define MAX_PATH PATH_MAX
- #if OSX
- // For OSX, use Linux defines except that the CoreCLR runtime
- // library has a different name
- #define CORECLR_FILE_NAME "libcoreclr.dylib"
- #else
- #define CORECLR_FILE_NAME "libcoreclr.so"
- #endif
-#endif
-
-// Function pointer types for the managed call and callback
-typedef int (*report_callback_ptr)(int progress);
-typedef char* (*doWork_ptr)(const char* jobName, int iterations, int dataSize, double* data, report_callback_ptr callbackFunction);
-
-void BuildTpaList(const char* directory, const char* extension, std::string& tpaList);
-int ReportProgressCallback(int progress);
-
-int main(int argc, char* argv[])
-{
- // Get the current executable's directory
- // This sample assumes that both CoreCLR and the
- // managed assembly to be loaded are next to this host
- // so we need to get the current path in order to locate those.
- char runtimePath[MAX_PATH];
-#if WINDOWS
- GetFullPathNameA(argv[0], MAX_PATH, runtimePath, NULL);
-#elif LINUX
- realpath(argv[0], runtimePath);
-#endif
- char *last_slash = strrchr(runtimePath, FS_SEPARATOR[0]);
- if (last_slash != NULL)
- *last_slash = 0;
-
- // Construct the CoreCLR path
- // For this sample, we know CoreCLR's path. For other hosts,
- // it may be necessary to probe for coreclr.dll/libcoreclr.so
- std::string coreClrPath(runtimePath);
- coreClrPath.append(FS_SEPARATOR);
- coreClrPath.append(CORECLR_FILE_NAME);
-
- // Construct the managed library path
- std::string managedLibraryPath(runtimePath);
- managedLibraryPath.append(FS_SEPARATOR);
- managedLibraryPath.append(MANAGED_ASSEMBLY);
-
- //
- // STEP 1: Load CoreCLR (coreclr.dll/libcoreclr.so)
- //
-#if WINDOWS
- //
- HMODULE coreClr = LoadLibraryExA(coreClrPath.c_str(), NULL, 0);
- //
-#elif LINUX
- void *coreClr = dlopen(coreClrPath.c_str(), RTLD_NOW | RTLD_LOCAL);
-#endif
- if (coreClr == NULL)
- {
- printf("ERROR: Failed to load CoreCLR from %s\n", coreClrPath.c_str());
- return -1;
- }
- else
- {
- printf("Loaded CoreCLR from %s\n", coreClrPath.c_str());
- }
-
- //
- // STEP 2: Get CoreCLR hosting functions
- //
-#if WINDOWS
- //
- coreclr_initialize_ptr initializeCoreClr = (coreclr_initialize_ptr)GetProcAddress(coreClr, "coreclr_initialize");
- coreclr_create_delegate_ptr createManagedDelegate = (coreclr_create_delegate_ptr)GetProcAddress(coreClr, "coreclr_create_delegate");
- coreclr_shutdown_ptr shutdownCoreClr = (coreclr_shutdown_ptr)GetProcAddress(coreClr, "coreclr_shutdown");
- //
-#elif LINUX
- coreclr_initialize_ptr initializeCoreClr = (coreclr_initialize_ptr)dlsym(coreClr, "coreclr_initialize");
- coreclr_create_delegate_ptr createManagedDelegate = (coreclr_create_delegate_ptr)dlsym(coreClr, "coreclr_create_delegate");
- coreclr_shutdown_ptr shutdownCoreClr = (coreclr_shutdown_ptr)dlsym(coreClr, "coreclr_shutdown");
-#endif
-
- if (initializeCoreClr == NULL)
- {
- printf("coreclr_initialize not found");
- return -1;
- }
-
- if (createManagedDelegate == NULL)
- {
- printf("coreclr_create_delegate not found");
- return -1;
- }
-
- if (shutdownCoreClr == NULL)
- {
- printf("coreclr_shutdown not found");
- return -1;
- }
-
- //
- // STEP 3: Construct properties used when starting the runtime
- //
-
- // Construct the trusted platform assemblies (TPA) list
- // This is the list of assemblies that .NET Core can load as
- // trusted system assemblies.
- // For this host (as with most), assemblies next to CoreCLR will
- // be included in the TPA list
- std::string tpaList;
- BuildTpaList(runtimePath, ".dll", tpaList);
-
- //
- // Define CoreCLR properties
- // Other properties related to assembly loading are common here,
- // but for this simple sample, TRUSTED_PLATFORM_ASSEMBLIES is all
- // that is needed. Check hosting documentation for other common properties.
- const char* propertyKeys[] = {
- "TRUSTED_PLATFORM_ASSEMBLIES" // Trusted assemblies
- };
-
- const char* propertyValues[] = {
- tpaList.c_str()
- };
- //
-
- //
- // STEP 4: Start the CoreCLR runtime
- //
-
- //
- void* hostHandle;
- unsigned int domainId;
-
- // This function both starts the .NET Core runtime and creates
- // the default (and only) AppDomain
- int hr = initializeCoreClr(
- runtimePath, // App base path
- "SampleHost", // AppDomain friendly name
- sizeof(propertyKeys) / sizeof(char*), // Property count
- propertyKeys, // Property names
- propertyValues, // Property values
- &hostHandle, // Host handle
- &domainId); // AppDomain ID
- //
-
- if (hr >= 0)
- {
- printf("CoreCLR started\n");
- }
- else
- {
- printf("coreclr_initialize failed - status: 0x%08x\n", hr);
- return -1;
- }
-
- //
- // STEP 5: Create delegate to managed code and invoke it
- //
-
- //
- doWork_ptr managedDelegate;
-
- // The assembly name passed in the third parameter is a managed assembly name
- // as described at https://docs.microsoft.com/dotnet/framework/app-domains/assembly-names
- hr = createManagedDelegate(
- hostHandle,
- domainId,
- "ManagedLibrary, Version=1.0.0.0",
- "ManagedLibrary.ManagedWorker",
- "DoWork",
- (void**)&managedDelegate);
- //
-
- if (hr >= 0)
- {
- printf("Managed delegate created\n");
- }
- else
- {
- printf("coreclr_create_delegate failed - status: 0x%08x\n", hr);
- return -1;
- }
-
- // Create sample data for the double[] argument of the managed method to be called
- double data[4];
- data[0] = 0;
- data[1] = 0.25;
- data[2] = 0.5;
- data[3] = 0.75;
-
- // Invoke the managed delegate and write the returned string to the console
- char* ret = managedDelegate("Test job", 5, sizeof(data) / sizeof(double), data, ReportProgressCallback);
-
- printf("Managed code returned: %s\n", ret);
-
- // Strings returned to native code must be freed by the native code
-#if WINDOWS
- CoTaskMemFree(ret);
-#elif LINUX
- free(ret);
-#endif
-
- //
- // STEP 6: Shutdown CoreCLR
- //
-
- //
- hr = shutdownCoreClr(hostHandle, domainId);
- //
-
- if (hr >= 0)
- {
- printf("CoreCLR successfully shutdown\n");
- }
- else
- {
- printf("coreclr_shutdown failed - status: 0x%08x\n", hr);
- }
-
- return 0;
-}
-
-#if WINDOWS
-// Win32 directory search for .dll files
-//
-void BuildTpaList(const char* directory, const char* extension, std::string& tpaList)
-{
- // This will add all files with a .dll extension to the TPA list.
- // This will include unmanaged assemblies (coreclr.dll, for example) that don't
- // belong on the TPA list. In a real host, only managed assemblies that the host
- // expects to load should be included. Having extra unmanaged assemblies doesn't
- // cause anything to fail, though, so this function just enumerates all dll's in
- // order to keep this sample concise.
- std::string searchPath(directory);
- searchPath.append(FS_SEPARATOR);
- searchPath.append("*");
- searchPath.append(extension);
-
- WIN32_FIND_DATAA findData;
- HANDLE fileHandle = FindFirstFileA(searchPath.c_str(), &findData);
-
- if (fileHandle != INVALID_HANDLE_VALUE)
- {
- do
- {
- // Append the assembly to the list
- tpaList.append(directory);
- tpaList.append(FS_SEPARATOR);
- tpaList.append(findData.cFileName);
- tpaList.append(PATH_DELIMITER);
-
- // Note that the CLR does not guarantee which assembly will be loaded if an assembly
- // is in the TPA list multiple times (perhaps from different paths or perhaps with different NI/NI.dll
- // extensions. Therefore, a real host should probably add items to the list in priority order and only
- // add a file if it's not already present on the list.
- //
- // For this simple sample, though, and because we're only loading TPA assemblies from a single path,
- // and have no native images, we can ignore that complication.
- }
- while (FindNextFileA(fileHandle, &findData));
- FindClose(fileHandle);
- }
-}
-//
-#elif LINUX
-// POSIX directory search for .dll files
-void BuildTpaList(const char* directory, const char* extension, std::string& tpaList)
-{
- DIR* dir = opendir(directory);
- struct dirent* entry;
- int extLength = strlen(extension);
-
- while ((entry = readdir(dir)) != NULL)
- {
- // This simple sample doesn't check for symlinks
- std::string filename(entry->d_name);
-
- // Check if the file has the right extension
- int extPos = filename.length() - extLength;
- if (extPos <= 0 || filename.compare(extPos, extLength, extension) != 0)
- {
- continue;
- }
-
- // Append the assembly to the list
- tpaList.append(directory);
- tpaList.append(FS_SEPARATOR);
- tpaList.append(filename);
- tpaList.append(PATH_DELIMITER);
-
- // Note that the CLR does not guarantee which assembly will be loaded if an assembly
- // is in the TPA list multiple times (perhaps from different paths or perhaps with different NI/NI.dll
- // extensions. Therefore, a real host should probably add items to the list in priority order and only
- // add a file if it's not already present on the list.
- //
- // For this simple sample, though, and because we're only loading TPA assemblies from a single path,
- // and have no native images, we can ignore that complication.
- }
-}
-#endif
-
-// Callback function passed to managed code to facilitate calling back into native code with status
-int ReportProgressCallback(int progress)
-{
- // Just print the progress parameter to the console and return -progress
- printf("Received status from managed code: %d\n", progress);
- return -progress;
-}
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/coreclrhost.h b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/coreclrhost.h
deleted file mode 100644
index 4981907c88fac..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithCoreClrHost/src/coreclrhost.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Retrieved from https://github.com/dotnet/runtime/blob/master/src/coreclr/src/hosts/inc/coreclrhost.h
-
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-//
-// APIs for hosting CoreCLR
-//
-
-#ifndef __CORECLR_HOST_H__
-#define __CORECLR_HOST_H__
-
-#if defined(_WIN32) && defined(_M_IX86)
-#define CORECLR_CALLING_CONVENTION __stdcall
-#else
-#define CORECLR_CALLING_CONVENTION
-#endif
-
-// For each hosting API, we define a function prototype and a function pointer
-// The prototype is useful for implicit linking against the dynamic coreclr
-// library and the pointer for explicit dynamic loading (dlopen, LoadLibrary)
-#define CORECLR_HOSTING_API(function, ...) \
- extern "C" int CORECLR_CALLING_CONVENTION function(__VA_ARGS__); \
- typedef int (CORECLR_CALLING_CONVENTION *function##_ptr)(__VA_ARGS__)
-
-//
-// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
-//
-// Parameters:
-// exePath - Absolute path of the executable that invoked the ExecuteAssembly (the native host application)
-// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
-// propertyCount - Number of properties (elements of the following two arguments)
-// propertyKeys - Keys of properties of the app domain
-// propertyValues - Values of properties of the app domain
-// hostHandle - Output parameter, handle of the created host
-// domainId - Output parameter, id of the created app domain
-//
-// Returns:
-// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
-//
-CORECLR_HOSTING_API(coreclr_initialize,
- const char* exePath,
- const char* appDomainFriendlyName,
- int propertyCount,
- const char** propertyKeys,
- const char** propertyValues,
- void** hostHandle,
- unsigned int* domainId);
-
-//
-// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
-//
-// Parameters:
-// hostHandle - Handle of the host
-// domainId - Id of the domain
-//
-// Returns:
-// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
-//
-CORECLR_HOSTING_API(coreclr_shutdown,
- void* hostHandle,
- unsigned int domainId);
-
-//
-// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
-//
-// Parameters:
-// hostHandle - Handle of the host
-// domainId - Id of the domain
-// latchedExitCode - Latched exit code after domain unloaded
-//
-// Returns:
-// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
-//
-CORECLR_HOSTING_API(coreclr_shutdown_2,
- void* hostHandle,
- unsigned int domainId,
- int* latchedExitCode);
-
-//
-// Create a native callable function pointer for a managed method.
-//
-// Parameters:
-// hostHandle - Handle of the host
-// domainId - Id of the domain
-// entryPointAssemblyName - Name of the assembly which holds the custom entry point
-// entryPointTypeName - Name of the type which holds the custom entry point
-// entryPointMethodName - Name of the method which is the custom entry point
-// delegate - Output parameter, the function stores a native callable function pointer to the delegate at the specified address
-//
-// Returns:
-// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
-//
-CORECLR_HOSTING_API(coreclr_create_delegate,
- void* hostHandle,
- unsigned int domainId,
- const char* entryPointAssemblyName,
- const char* entryPointTypeName,
- const char* entryPointMethodName,
- void** delegate);
-
-//
-// Execute a managed assembly with given arguments
-//
-// Parameters:
-// hostHandle - Handle of the host
-// domainId - Id of the domain
-// argc - Number of arguments passed to the executed assembly
-// argv - Array of arguments passed to the executed assembly
-// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
-// exitCode - Exit code returned by the executed assembly
-//
-// Returns:
-// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
-//
-CORECLR_HOSTING_API(coreclr_execute_assembly,
- void* hostHandle,
- unsigned int domainId,
- int argc,
- const char** argv,
- const char* managedAssemblyPath,
- unsigned int* exitCode);
-
-#undef CORECLR_HOSTING_API
-
-#endif // __CORECLR_HOST_H__
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/readme.md b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/readme.md
index 3fa24b3775b42..6e893fdf3d3ac 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/readme.md
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/readme.md
@@ -1,20 +1,25 @@
# .NET Core Hosting Sample
-This project demonstrates a way for a native process to host .NET Core using the `nethost` and `hostfxr` libraries. Documentation on the `nethost` and `hostfxr` APIs can be found [here](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/native-hosting.md).
+This project demonstrates a way for a native process to host .NET Core using the `nethost` and `hostfxr` libraries. Documentation on the `nethost` and `hostfxr` APIs can be found [here](https://github.com/dotnet/runtime/blob/main/docs/design/features/native-hosting.md).
+
+This sample is part of the [.NET Core hosting tutorial](https://docs.microsoft.com/dotnet/core/tutorials/netcore-hosting). Please see that topic for a more detailed explanation of the sample and the steps necessary to host .NET Core.
+
+The host is small and bypasses a lot of complexity (thorough error checking, etc.) that a real host would have. Hopefully by remaining simple, though, it will be useful for demonstrating the core concepts of hosting managed .NET Core code in a native process.
## Key Features
-Demonstrates how to locate and initialize .NET Core 3.0 from a non-.NET Core process and subsequently load and call into a .NET Core assembly.
+Demonstrates how to locate and initialize .NET Core runtime from a non-.NET Core process and subsequently load and call into a .NET Core assembly.
-The `nethost` header and library are part of the Microsoft.NETCore.DotNetAppHost package and are also installed as a runtime pack by the .NET SDK. The library should be deployed alongside the host. This sample uses the files installed with the .NET SDK.
+The `nethost` header and library are part of the `Microsoft.NETCore.DotNetAppHost` package and are also installed as a runtime pack by the .NET Core SDK. The library should be deployed alongside the host. This sample uses the files installed with the .NET Core SDK.
+*Note: The `Microsoft.NETCore.DotNetAppHost` package is a [metapackage](https://docs.microsoft.com/dotnet/core/packages#metapackages) that doesn't actually contain the files. It only references RID-specific packages that contain the files. For example, the package with the actual files for `linux-x64` is `runtime.linux-x64.Microsoft.NETCore.DotNetAppHost`.*
-The `coreclr_delegates.h` and `hostfxr.h` files are copied from the [core-setup](https://github.com/dotnet/core-setup) repo.
+The `coreclr_delegates.h` and `hostfxr.h` files are copied from the [dotnet/runtime](https://github.com/dotnet/runtime) repo - [coreclr_delegates.h](https://github.com/dotnet/runtime/blob/main/src/installer/corehost/cli/coreclr_delegates.h) and [hostfxr.h](https://github.com/dotnet/runtime/blob/main/src/installer/corehost/cli/hostfxr.h).
Additional comments are contained in source and project files.
## Prerequisites
-* [.NET Core 3.0 SDK](https://dotnet.microsoft.com/download) or a later version
+* [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download) or a later version
* C++ compiler
* Windows: `cl.exe`
@@ -24,10 +29,9 @@ Additional comments are contained in source and project files.
1. In order to build and run, all prerequisites must be installed. The following are also required:
- * The C++ compiler (`cl.exe` or `g++`) must be on the path.
- * On Windows, a [Developer Command Prompt for Visual Studio](https://docs.microsoft.com/cpp/build/building-on-the-command-line#developer_command_prompt_shortcuts) should be used.
- * The C++ compiler (`cl.exe` or `g++`) and `dotnet` must be the same bitness (32-bit or 64-bit).
- * On Windows, the default developer command prompt for VS uses the 32-bit compilers, but `dotnet` is typically 64-bit by default. Make sure to select the "x64 Native Tools Command Prompt for VS 2019" (or 2017).
+ * On Linux/macOS, the C++ compiler (`g++`) must be on the path.
+ * The C++ compiler (`cl.exe` or `g++`) and `dotnet` must be the same bitness (32-bit versus 64-bit).
+ * On Windows, the sample is set up to use the bitness of `dotnet` to find the corresponding `cl.exe`
1. Navigate to the root directory.
@@ -40,7 +44,7 @@ Additional comments are contained in source and project files.
The expected output will come from the `DotNetLib` class library and include the arguments passed to the managed library from the host:
-```output
+```console
Hello, world! from Lib [count: 1]
-- message: from host!
-- number: 0
@@ -50,11 +54,14 @@ Hello, world! from Lib [count: 2]
Hello, world! from Lib [count: 3]
-- message: from host!
-- number: 2
+Hello, world! from CustomEntryPoint in Lib
+-- message: from host!
+-- number: -1
```
Note: The way the sample is built is relatively complicated. The goal is that it's possible to build and run the sample with simple `dotnet run` with minimal requirements on pre-installed tools. Typically, real-world projects that have both managed and native components will use different build systems for each; for example, msbuild/dotnet for managed and CMake for native.
## Visual Studio support
-The `src\HostWithHostFxr.sln` solution file can be used to open the sample in Visual Studio 2019. In order to be able to build from Visual Studio, though, it has to be started from the correct developer environment. From the developer environment console, start it with `devenv src\HostWithHostFxr.sln`. With that, the solution can be built. To run it, set the startup project to `build/NativeHost`.
+The `src\HostWithHostFxr.sln` solution file can be used to open the sample in Visual Studio 2019. To run the sample, set the startup project to `build/NativeHost`.
Note that with mixed mode debugging (that is, a debugger that can see both native and managed code at the same time), there's a known limitation where no breakpoints will be hit before the runtime starts. So it is not possible to debug the parts of the sample before (and including) the call to `load_assembly_and_get_function_pointer` like that. To debug those, start the process from a native-only debugger.
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/DotNetLib.csproj b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/DotNetLib.csproj
index ff9ddb2397c6d..07ea8c230a9ac 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/DotNetLib.csproj
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/DotNetLib.csproj
@@ -1,23 +1,13 @@
- netcoreapp3.1
+ net5.0true
-
-
-
-
-
-
-
-
-
-
-
-
+
+ $(BinRoot)/$(Configuration)/
+ false
+
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/Lib.cs b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/Lib.cs
index 505670abb4a31..60d68d1e747c3 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/Lib.cs
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/DotNetLib/Lib.cs
@@ -22,14 +22,34 @@ public static int Hello(IntPtr arg, int argLength)
}
LibArgs libArgs = Marshal.PtrToStructure(arg);
+ Console.WriteLine($"Hello, world! from {nameof(Lib)} [count: {s_CallCount++}]");
+ PrintLibArgs(libArgs);
+ return 0;
+ }
+
+ public delegate void CustomEntryPointDelegate(LibArgs libArgs);
+ public static void CustomEntryPoint(LibArgs libArgs)
+ {
+ Console.WriteLine($"Hello, world! from {nameof(CustomEntryPoint)} in {nameof(Lib)}");
+ PrintLibArgs(libArgs);
+ }
+
+#if NET5_0
+ [UnmanagedCallersOnly]
+ public static void CustomEntryPointUnmanaged(LibArgs libArgs)
+ {
+ CustomEntryPoint(libArgs);
+ }
+#endif
+
+ private static void PrintLibArgs(LibArgs libArgs)
+ {
string message = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Marshal.PtrToStringUni(libArgs.Message)
: Marshal.PtrToStringUTF8(libArgs.Message);
- Console.WriteLine($"Hello, world! from {nameof(Lib)} [count: {s_CallCount++}]");
Console.WriteLine($"-- message: {message}");
Console.WriteLine($"-- number: {libArgs.Number}");
- return 0;
}
}
}
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/HostWithHostFxr.sln b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/HostWithHostFxr.sln
index bc4f92ccbacb0..739819fadc4e0 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/HostWithHostFxr.sln
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/HostWithHostFxr.sln
@@ -23,9 +23,7 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Debug|x64.ActiveCfg = Debug|x64
- {B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Debug|x64.Build.0 = Debug|x64
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Debug|x86.ActiveCfg = Debug|Win32
- {B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Debug|x86.Build.0 = Debug|Win32
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Release|Any CPU.ActiveCfg = Release|Win32
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Release|x64.ActiveCfg = Release|x64
{B99BC289-621D-4DB6-A964-2D869F8E0DD3}.Release|x64.Build.0 = Release|x64
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.csproj b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.csproj
index b81432a870d31..66e5e7ca3d8b7 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.csproj
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1
+ net5.0
@@ -19,13 +19,49 @@
PreserveNewestfalse
+
+ PreserveNewest
+ false
+
-
-
+
+ $(BinRoot)/$(Configuration)
+ nativehost
+
+ $([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)
+ $(MSBuildThisFileDirectory)obj/$(Configuration)/$(NativePlatform)/
+ $(MSBuildThisFileDirectory)
+
+
+
+
+ x64
+ x86
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- $(BinRoot)/$(Configuration)
+
+
+ .exe
+ $(NativeBinDir)/$(NativeOutputName)$(NativeOutputExtension)
+
+ @(NativeSource-> '"%(RootDir)%(Directory)%(Filename)%(Extension)"', ' ')
+
$(NetCoreTargetingPackRoot)/Microsoft.NETCore.App.Host.$(NETCoreSdkRuntimeIdentifier)/$(BundledNETCoreAppPackageVersion)/runtimes/$(NETCoreSdkRuntimeIdentifier)/nativenethost.dll
@@ -33,19 +69,53 @@
libnethost.dylib
-
+
+
+
+
+
+
+ -I$(NativeHostDirectory)inc -I"$(NetHostDir)"
+ -g
+
+
+ -D LINUX
+ -ldl -lnethost -lpthread -L"$(NetHostDir)" -Wl,-rpath,'$ORIGIN',--disable-new-dtags
+
+
+ -D OSX
+ -ldl -lnethost -lpthread -L"$(NetHostDir)" -Wl,-rpath,'@loader_path'
+
+
+
-
+
+
+
+
+
+ @(MSVCIncludePaths-> '/I "%(RootDir)%(Directory)%(Filename)"', ' ')
+ $(IncPaths) /I inc /I "$(NetHostDir)"
+ /EHsc /Od /GS /sdl /Zi
+ /D WINDOWS
+ @(MSVCLibPaths-> '/LIBPATH:"%(RootDir)%(Directory)%(Filename)"', ' ')
+ $(LibPaths) "$(NetHostDir)\nethost.lib"
+
-
+
-
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj
index c7dc4f78a887a..c8e6cae84501e 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj
@@ -89,8 +89,9 @@
Level3Disabledtrue
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ WINDOWS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)true
+ inc;inc.vs;%(AdditionalIncludeDirectories)Console
@@ -104,8 +105,9 @@
Level3Disabledtrue
- _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ WINDOWS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)true
+ inc;%(AdditionalIncludeDirectories)Console
@@ -151,6 +153,7 @@
+
@@ -160,4 +163,4 @@
-
\ No newline at end of file
+
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj.filters b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj.filters
index 3373a8b6aacc9..593a92e372d45 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj.filters
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/NativeHost.vs.vcxproj.filters
@@ -17,6 +17,9 @@
Header Files
+
+ Header Files
+
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc.vs/nethost.h b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc.vs/nethost.h
new file mode 100644
index 0000000000000..31adde5e8dafb
--- /dev/null
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc.vs/nethost.h
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __NETHOST_H__
+#define __NETHOST_H__
+
+#include
+
+#ifdef _WIN32
+ #ifdef NETHOST_EXPORT
+ #define NETHOST_API __declspec(dllexport)
+ #else
+ // Consuming the nethost as a static library
+ // Shouldn't export attempt to dllimport.
+ #ifdef NETHOST_USE_AS_STATIC
+ #define NETHOST_API
+ #else
+ #define NETHOST_API __declspec(dllimport)
+ #endif
+ #endif
+
+ #define NETHOST_CALLTYPE __stdcall
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
+#else
+ #ifdef NETHOST_EXPORT
+ #define NETHOST_API __attribute__((__visibility__("default")))
+ #else
+ #define NETHOST_API
+ #endif
+
+ #define NETHOST_CALLTYPE
+ typedef char char_t;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Parameters for get_hostfxr_path
+//
+// Fields:
+// size
+// Size of the struct. This is used for versioning.
+//
+// assembly_path
+// Path to the compenent's assembly.
+// If specified, hostfxr is located as if the assembly_path is the apphost
+//
+// dotnet_root
+// Path to directory containing the dotnet executable.
+// If specified, hostfxr is located as if an application is started using
+// 'dotnet app.dll', which means it will be searched for under the dotnet_root
+// path and the assembly_path is ignored.
+//
+struct get_hostfxr_parameters {
+ size_t size;
+ const char_t *assembly_path;
+ const char_t *dotnet_root;
+};
+
+//
+// Get the path to the hostfxr library
+//
+// Parameters:
+// buffer
+// Buffer that will be populated with the hostfxr path, including a null terminator.
+//
+// buffer_size
+// [in] Size of buffer in char_t units.
+// [out] Size of buffer used in char_t units. If the input value is too small
+// or buffer is nullptr, this is populated with the minimum required size
+// in char_t units for a buffer to hold the hostfxr path
+//
+// get_hostfxr_parameters
+// Optional. Parameters that modify the behaviour for locating the hostfxr library.
+// If nullptr, hostfxr is located using the enviroment variable or global registration
+//
+// Return value:
+// 0 on success, otherwise failure
+// 0x80008098 - buffer is too small (HostApiBufferTooSmall)
+//
+// Remarks:
+// The full search for the hostfxr library is done on every call. To minimize the need
+// to call this function multiple times, pass a large buffer (e.g. PATH_MAX).
+//
+NETHOST_API int NETHOST_CALLTYPE get_hostfxr_path(
+ char_t * buffer,
+ size_t * buffer_size,
+ const struct get_hostfxr_parameters *parameters);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // __NETHOST_H__
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/coreclr_delegates.h b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/coreclr_delegates.h
index 253e1d5b15e02..914ab592df914 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/coreclr_delegates.h
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/coreclr_delegates.h
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
#ifndef __CORECLR_DELEGATES_H__
#define __CORECLR_DELEGATES_H__
@@ -8,27 +7,41 @@
#include
#if defined(_WIN32)
-#define CORECLR_DELEGATE_CALLTYPE __stdcall
-#ifdef _WCHAR_T_DEFINED
-typedef wchar_t char_t;
+ #define CORECLR_DELEGATE_CALLTYPE __stdcall
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
#else
-typedef unsigned short char_t;
-#endif
-#else
-#define CORECLR_DELEGATE_CALLTYPE
-typedef char char_t;
+ #define CORECLR_DELEGATE_CALLTYPE
+ typedef char char_t;
#endif
+#define UNMANAGEDCALLERSONLY_METHOD ((const char_t*)-1)
+
// Signature of delegate returned by coreclr_delegate_type::load_assembly_and_get_function_pointer
typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_and_get_function_pointer_fn)(
const char_t *assembly_path /* Fully qualified path to assembly */,
const char_t *type_name /* Assembly qualified type name */,
const char_t *method_name /* Public static method name compatible with delegateType */,
- const char_t *delegate_type_name /* Assembly qualified delegate type name or null */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
void *reserved /* Extensibility parameter (currently unused and must be 0) */,
/*out*/ void **delegate /* Pointer where to store the function pointer result */);
// Signature of delegate returned by load_assembly_and_get_function_pointer_fn when delegate_type_name == null (default)
typedef int (CORECLR_DELEGATE_CALLTYPE *component_entry_point_fn)(void *arg, int32_t arg_size_in_bytes);
+typedef int (CORECLR_DELEGATE_CALLTYPE *get_function_pointer_fn)(
+ const char_t *type_name /* Assembly qualified type name */,
+ const char_t *method_name /* Public static method name compatible with delegateType */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null,
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
+ void *load_context /* Extensibility parameter (currently unused and must be 0) */,
+ void *reserved /* Extensibility parameter (currently unused and must be 0) */,
+ /*out*/ void **delegate /* Pointer where to store the function pointer result */);
+
#endif // __CORECLR_DELEGATES_H__
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/hostfxr.h b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/hostfxr.h
index 5b61c47240fdc..809bf5beccad4 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/hostfxr.h
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/inc/hostfxr.h
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
#ifndef __HOSTFXR_H__
#define __HOSTFXR_H__
@@ -27,7 +26,8 @@ enum hostfxr_delegate_type
hdt_winrt_activation,
hdt_com_register,
hdt_com_unregister,
- hdt_load_assembly_and_get_function_pointer
+ hdt_load_assembly_and_get_function_pointer,
+ hdt_get_function_pointer,
};
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_fn)(const int argc, const char_t **argv);
@@ -37,48 +37,252 @@ typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_startupinfo_fn)(
const char_t *host_path,
const char_t *dotnet_root,
const char_t *app_path);
+typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_main_bundle_startupinfo_fn)(
+ const int argc,
+ const char_t** argv,
+ const char_t* host_path,
+ const char_t* dotnet_root,
+ const char_t* app_path,
+ int64_t bundle_header_offset);
typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message);
+
+//
+// Sets a callback which is to be used to write errors to.
+//
+// Parameters:
+// error_writer
+// A callback function which will be invoked every time an error is to be reported.
+// Or nullptr to unregister previously registered callback and return to the default behavior.
+// Return value:
+// The previously registered callback (which is now unregistered), or nullptr if no previous callback
+// was registered
+//
+// The error writer is registered per-thread, so the registration is thread-local. On each thread
+// only one callback can be registered. Subsequent registrations overwrite the previous ones.
+//
+// By default no callback is registered in which case the errors are written to stderr.
+//
+// Each call to the error writer is sort of like writing a single line (the EOL character is omitted).
+// Multiple calls to the error writer may occure for one failure.
+//
+// If the hostfxr invokes functions in hostpolicy as part of its operation, the error writer
+// will be propagated to hostpolicy for the duration of the call. This means that errors from
+// both hostfxr and hostpolicy will be reported through the same error writer.
+//
typedef hostfxr_error_writer_fn(HOSTFXR_CALLTYPE *hostfxr_set_error_writer_fn)(hostfxr_error_writer_fn error_writer);
typedef void* hostfxr_handle;
-typedef struct hostfxr_initialize_parameters
+struct hostfxr_initialize_parameters
{
size_t size;
const char_t *host_path;
const char_t *dotnet_root;
-} hostfxr_initialize_parameters;
+};
+//
+// Initializes the hosting components for a dotnet command line running an application
+//
+// Parameters:
+// argc
+// Number of argv arguments
+// argv
+// Command-line arguments for running an application (as if through the dotnet executable).
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// HostInvalidState - Hosting components are already initialized
+//
+// This function parses the specified command-line arguments to determine the application to run. It will
+// then find the corresponding .runtimeconfig.json and .deps.json with which to resolve frameworks and
+// dependencies and prepare everything needed to load the runtime.
+//
+// This function only supports arguments for running an application. It does not support SDK commands.
+//
+// This function does not load the runtime.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_dotnet_command_line_fn)(
int argc,
const char_t **argv,
- const hostfxr_initialize_parameters *parameters,
+ const struct hostfxr_initialize_parameters *parameters,
/*out*/ hostfxr_handle *host_context_handle);
+
+//
+// Initializes the hosting components using a .runtimeconfig.json file
+//
+// Parameters:
+// runtime_config_path
+// Path to the .runtimeconfig.json file
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// Success_HostAlreadyInitialized - Config is compatible with already initialized hosting components
+// Success_DifferentRuntimeProperties - Config has runtime properties that differ from already initialized hosting components
+// CoreHostIncompatibleConfig - Config is incompatible with already initialized hosting components
+//
+// This function will process the .runtimeconfig.json to resolve frameworks and prepare everything needed
+// to load the runtime. It will only process the .deps.json from frameworks (not any app/component that
+// may be next to the .runtimeconfig.json).
+//
+// This function does not load the runtime.
+//
+// If called when the runtime has already been loaded, this function will check if the specified runtime
+// config is compatible with the existing runtime.
+//
+// Both Success_HostAlreadyInitialized and Success_DifferentRuntimeProperties codes are considered successful
+// initializations. In the case of Success_DifferentRuntimeProperties, it is left to the consumer to verify that
+// the difference in properties is acceptable.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_runtime_config_fn)(
const char_t *runtime_config_path,
- const hostfxr_initialize_parameters*parameters,
+ const struct hostfxr_initialize_parameters *parameters,
/*out*/ hostfxr_handle *host_context_handle);
+//
+// Gets the runtime property value for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Out parameter. Pointer to a buffer with the property value.
+//
+// Return value:
+// The error code result.
+//
+// The buffer pointed to by value is owned by the host context. The lifetime of the buffer is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// property value for the active host context.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_property_value_fn)(
const hostfxr_handle host_context_handle,
const char_t *name,
/*out*/ const char_t **value);
+
+//
+// Sets the value of a runtime property for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Value to set
+//
+// Return value:
+// The error code result.
+//
+// Setting properties is only supported for the first host context, before the runtime has been loaded.
+//
+// If the property already exists in the host context, it will be overwritten. If value is nullptr, the
+// property will be removed.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_set_runtime_property_value_fn)(
const hostfxr_handle host_context_handle,
const char_t *name,
const char_t *value);
+
+//
+// Gets all the runtime properties for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// count
+// [in] Size of the keys and values buffers
+// [out] Number of properties returned (size of keys/values buffers used). If the input value is too
+// small or keys/values is nullptr, this is populated with the number of available properties
+// keys
+// Array of pointers to buffers with runtime property keys
+// values
+// Array of pointers to buffers with runtime property values
+//
+// Return value:
+// The error code result.
+//
+// The buffers pointed to by keys and values are owned by the host context. The lifetime of the buffers is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// properties for the active host context.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_properties_fn)(
const hostfxr_handle host_context_handle,
/*inout*/ size_t * count,
/*out*/ const char_t **keys,
/*out*/ const char_t **values);
+//
+// Load CoreCLR and run the application for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// If the app was successfully run, the exit code of the application. Otherwise, the error code result.
+//
+// The host_context_handle must have been initialized using hostfxr_initialize_for_dotnet_command_line.
+//
+// This function will not return until the managed application exits.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_run_app_fn)(const hostfxr_handle host_context_handle);
+
+//
+// Gets a typed delegate from the currently loaded CoreCLR or from a newly created one.
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// type
+// Type of runtime delegate requested
+// delegate
+// An out parameter that will be assigned the delegate.
+//
+// Return value:
+// The error code result.
+//
+// If the host_context_handle was initialized using hostfxr_initialize_for_runtime_config,
+// then all delegate types are supported.
+// If the host_context_handle was initialized using hostfxr_initialize_for_dotnet_command_line,
+// then only the following delegate types are currently supported:
+// hdt_load_assembly_and_get_function_pointer
+// hdt_get_function_pointer
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_delegate_fn)(
const hostfxr_handle host_context_handle,
enum hostfxr_delegate_type type,
/*out*/ void **delegate);
+//
+// Closes an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// The error code result.
+//
typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_close_fn)(const hostfxr_handle host_context_handle);
#endif //__HOSTFXR_H__
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp
index b59605aec587f..6dffe1a4b828e 100644
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp
+++ b/samples/snippets/core/tutorials/netcore-hosting/csharp/HostWithHostFxr/src/NativeHost/nativehost.cpp
@@ -128,6 +128,39 @@ int main(int argc, char *argv[])
//
}
+#ifdef NET5_0
+ // Function pointer to managed delegate with non-default signature
+ typedef void (CORECLR_DELEGATE_CALLTYPE *custom_entry_point_fn)(lib_args args);
+ custom_entry_point_fn custom = nullptr;
+ rc = load_assembly_and_get_function_pointer(
+ dotnetlib_path.c_str(),
+ dotnet_type,
+ STR("CustomEntryPointUnmanaged") /*method_name*/,
+ UNMANAGEDCALLERSONLY_METHOD,
+ nullptr,
+ (void**)&custom);
+ assert(rc == 0 && custom != nullptr && "Failure: load_assembly_and_get_function_pointer()");
+#else
+ // Function pointer to managed delegate with non-default signature
+ typedef void (CORECLR_DELEGATE_CALLTYPE *custom_entry_point_fn)(lib_args args);
+ custom_entry_point_fn custom = nullptr;
+ rc = load_assembly_and_get_function_pointer(
+ dotnetlib_path.c_str(),
+ dotnet_type,
+ STR("CustomEntryPoint") /*method_name*/,
+ STR("DotNetLib.Lib+CustomEntryPointDelegate, DotNetLib") /*delegate_type_name*/,
+ nullptr,
+ (void**)&custom);
+ assert(rc == 0 && custom != nullptr && "Failure: load_assembly_and_get_function_pointer()");
+#endif
+
+ lib_args args
+ {
+ STR("from host!"),
+ -1
+ };
+ custom(args);
+
return EXIT_SUCCESS;
}
diff --git a/samples/snippets/core/tutorials/netcore-hosting/csharp/README.md b/samples/snippets/core/tutorials/netcore-hosting/csharp/README.md
deleted file mode 100644
index 929b0be5d87e0..0000000000000
--- a/samples/snippets/core/tutorials/netcore-hosting/csharp/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Sample .NET Core Hosts
-
-This folder contains sample code demonstrating how to host managed .NET Core code in a native process. These hosts bypass the usual `dotnet` host and launch managed code directly.
-
-There are three samples demonstrating three different hosting interfaces for .NET Core.
-
-1. The [HostWithHostFxr](HostWithHostFxr) folder demonstrates how to host the .NET Core runtime using the `nethost` and `hostfxr` libraries' APIs. These APIs were introduced in .NET Core 3.0 and are the recommended method of hosting .NET Core 3.0 and above. These entry points handle the complexity of finding and setting up the runtime for initialization. This host demonstrates calling from native code into a static managed method and passing it a message to display.
-1. The [HostWithCoreClrHost](HostWithCoreClrHost) folder demonstrates how to host the .NET Core runtime using the newer `coreclrhost.h` API. This API is the preferred method of hosting .NET Core 2.2 and below. This host demonstrates calling from native code into a static managed method and supplying a function pointer for the managed code to use to call back into the host.
-
-These hosts are small and bypass a lot of complexity (probing for assemblies in multiple locations, thorough error checking, etc.) that a real host would have. Hopefully by remaining simple, though, they will be useful for demonstrating the core concepts of hosting managed .NET Core code in a native process. Other (more real-world) hosts which may be useful as a guide can be found in .NET Core product source in the [dotnet/runtime](https://github.com/dotnet/runtime/tree/main/src/coreclr/hosts) repository.
-
-These samples are part of the [.NET Core hosting tutorial](https://docs.microsoft.com/dotnet/core/tutorials/netcore-hosting). Please see that topic for a more detailed explanation of the samples and the steps necessary to host .NET Core.