.NET NativeAOT
compiles your .NET application to a native executable. By default when you
publish an application as NativeAOT, the NativeAOT build system includes its
own unmanaged main function that will call your applications Main function.
Some applications need to run native code before the managed main function.
Starting in .NET 8, NativeAOT supports the CustomNativeMain property.
When set to true in your .csproj file, this property causes the NativeAOT build
system to not include an unmanaged main function. Instead you have to supply
one using a NativeLibrary item in the .csproj file.
In your unmanaged main function, your program can call
UnmanagedCallersOnly
functions. Your unmanaged main function can manipulate the command line arguments
argc and argv before passing them to the __managed__Main function to
execute the managed main function.
The NativeAOT runtime will be initialized on the first call to a reverse-P/Invoke
function. UnmanagedCallersOnly functions and __managed__Main are reverse-P/Invoke
functions.
See the src/CustomMain folder for an example.
One option is a module initializer. This facility allows executing C# functions at assembly load time. In NativeAOT, which does not have the concept of loading an assembly, all module initializers are run before the managed main.
A module initializer is less complicated to add to an application, as you don't have to integrate building unmanaged code into the build system. Conventional, non-NativeAOT .NET applications also support module initializers.