Prototype for a .NET managed assembly to expose a native export.
This work is inspired by work in the Xamarian, CoreRT, and DllExport projects.
- .NET 5.0.100-preview.5.20258.4 or greater.
- C99 compatible compiler.
Windows:
- Visual Studio 2015 or greater.
- Windows 10 SDK - Installed with Visual Studio.
- 32 and 64 bit compilation supported.
macOS:
- clang compiler on the path.
- 64 bit compilation supported.
Linux:
- clang compiler on the path.
- 64 bit compilation supported.
-
The exported function must be marked
static
andpublic
. -
The type exporting the function cannot be a nested type.
-
Using
DNNE.ExportAttribute
to export a method requires aDelegate
of the appropriate type and name to be at the same scope as the export. The naming convention is<METHODNAME>Delegate
For example:public class Exports { public delegate int MyExportDelegate(int a); [DNNE.Export(EntryPoint = "FancyName")] public static int MyExport(int a) { return a; } }
-
Using
UnmanagedCallersOnlyAttribute
to export a method has noDelegate
requirement unlike when usingDNNE.ExportAttribute
.
The native API is defined in src/platform/dnne.h
.
The DNNE_ASSEMBLY_NAME
must be set during compilation to indicate the name of the managed assembly to load. The assembly name should not include the extension. For example, if the managed assembly on disk is called ClassLib.dll
, the expected assembly name is ClassLib
.
The generated source will need to be linked against the nethost
library as either a static lib (libnethost.[lib|a]
) or dynamic/shared library (nethost.lib
). If the latter linking is performed, the nethost.[dll|so|dylib]
will need to be deployed with the export binary or be on the path at run time.
The set_failure_callback()
function can be used prior to calling an export to set a callback in the event runtime load or export discovery fails.
Failure to load the runtime or find an export results in the native library calling abort()
.
-
Add the following attribute definition to the managed project or alternatively use the existing
UnmanagedCallersOnlyAttribute
:namespace DNNE { internal class ExportAttribute : Attribute { public ExportAttribute() { } public string EntryPoint { get; set; } } }
The calling convention of the export will be the default for the .NET runtime on that platform. See the description of
CallingConvention.Winapi
. The calling convention can be set when usingUnmanagedCallersOnlyAttribute
. -
Adorn the desired managed function with
DNNE.ExportAttribute
orUnmanagedCallersOnlyAttribute
.- Optionally set the
EntryPoint
property to indicate the name of the native export. This property is available on both of the attributes. - If the
EntryPoint
property isnull
, the name of the mananged function is used. This default name will not include the namespace or class containing the function. - User supplied values in
EntryPoint
will not be modified or validated in any manner. This string will be consume by a C compiler and should therefore adhere to the C language's restrictions on function names.
- Optionally set the
-
Set the
<EnableDynamicLoading>true</EnableDynamicLoading>
property in the managed project containing the methods to export. This will produce a*.runtimeconfig.json
that is needed to activate the runtime during export dispatch.
-
The DNNE NuPkg is published on NuGet.org, but can also be built locally.
-
Building the DNNE NuPkg locally is done by running
pack
ondnne-gen.csproj
.> dotnet pack dnne-gen.csproj
-
-
Add the NuPkg to the target managed project.
- If NuPkg was built locally, remember to update the projects
nuget.config
to point at the local location of the recently built DNNE NuPkg.
<ItemGroup> <PackageReference Include="DNNE" Version="1.*" /> </ItemGroup>
- If NuPkg was built locally, remember to update the projects
-
Build the managed project to generate the native binary. The native binary will have a
NE
suffix and the system extension for dynamic/shared native libraries (i.e..dll
,.so
,.dylib
). -
Deploy the native binary, managed assembly and associated
*.json
files for consumption from a native process.
-
Run the dnne-gen tool on the managed assembly.
-
Take the generated source from
dnne-gen
and the DNNE platform source to compile a native binary with the desired native exports. See the Native API section for build details. -
Deploy the native binary, managed assembly and associated
*.json
files for consumption from a native process.