From 4b90d162502d65f20a89331898cd8a0b3eea8fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Rold=C3=A1n=20Etcheverry?= Date: Sun, 27 Feb 2022 21:57:52 +0100 Subject: C#: Initial NativeAOT support This commit adds initial support for games exported as NativeAOT shared libraries. At this moment, the NativeAOT runtime is experimental. Additionally, Godot is not trim-safe as it still makes some use of reflection. For the time being, a rd.xml file is needed to prevent code triming: ``` ``` These are the csproj changes for publishing: ``` Shared ``` More info: - https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/compiling.md - https://github.com/dotnet/runtimelab/tree/feature/NativeAOT/samples/NativeLibrary - https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/rd-xml-format.md --- modules/mono/glue/GodotSharp/GodotPlugins/Main.cs | 12 +++++++---- .../GodotSharp/Core/Bridge/ScriptManagerBridge.cs | 14 ++++++------ .../Core/NativeInterop/GodotDllImportResolver.cs | 25 +++++++++------------- 3 files changed, 26 insertions(+), 25 deletions(-) (limited to 'modules/mono/glue') diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs index 0cb9e57530..2a2e147eaa 100644 --- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs +++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs @@ -20,22 +20,26 @@ namespace GodotPlugins AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ?? AssemblyLoadContext.Default; + private static DllImportResolver? _dllImportResolver; + // Right now we do it this way for simplicity as hot-reload is disabled. It will need to be changed later. [UnmanagedCallersOnly] // ReSharper disable once UnusedMember.Local - private static unsafe godot_bool InitializeFromEngine(godot_bool editorHint, + private static unsafe godot_bool InitializeFromEngine(IntPtr godotDllHandle, godot_bool editorHint, PluginsCallbacks* pluginsCallbacks, ManagedCallbacks* managedCallbacks) { try { + _dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport; + SharedAssemblies.Add(CoreApiAssembly.GetName()); - NativeLibrary.SetDllImportResolver(CoreApiAssembly, GodotDllImportResolver.OnResolveDllImport); + NativeLibrary.SetDllImportResolver(CoreApiAssembly, _dllImportResolver); if (editorHint.ToBool()) { _editorApiAssembly = Assembly.Load("GodotSharpEditor"); SharedAssemblies.Add(_editorApiAssembly.GetName()); - NativeLibrary.SetDllImportResolver(_editorApiAssembly, GodotDllImportResolver.OnResolveDllImport); + NativeLibrary.SetDllImportResolver(_editorApiAssembly, _dllImportResolver); } *pluginsCallbacks = new() @@ -97,7 +101,7 @@ namespace GodotPlugins var assembly = LoadPlugin(assemblyPath); - NativeLibrary.SetDllImportResolver(assembly, GodotDllImportResolver.OnResolveDllImport); + NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!); var method = assembly.GetType("GodotTools.GodotSharpEditor")? .GetMethod("InternalCreateInstance", diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 71736a65c7..61987c6466 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -39,7 +39,12 @@ namespace Godot.Bridge try { - Type nativeType = TypeGetProxyClass(nativeTypeName); + using var stringName = StringName.CreateTakingOwnershipOfDisposableValue( + NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName))); + string nativeTypeNameStr = stringName.ToString(); + + Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException( + "Wrapper class not found for type: " + nativeTypeNameStr); var obj = (Object)FormatterServices.GetUninitializedObject(nativeType); var ctor = nativeType.GetConstructor( @@ -171,12 +176,9 @@ namespace Godot.Bridge } } - private static unsafe Type TypeGetProxyClass(godot_string_name* nativeTypeName) + private static Type TypeGetProxyClass(string nativeTypeNameStr) { // Performance is not critical here as this will be replaced with a generated dictionary. - using var stringName = StringName.CreateTakingOwnershipOfDisposableValue( - NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName))); - string nativeTypeNameStr = stringName.ToString(); if (nativeTypeNameStr[0] == '_') nativeTypeNameStr = nativeTypeNameStr.Substring(1); @@ -186,7 +188,7 @@ namespace Godot.Bridge if (wrapperType == null) { wrapperType = AppDomain.CurrentDomain.GetAssemblies() - .First(a => a.GetName().Name == "GodotSharpEditor") + .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor")? .GetType("Godot." + nativeTypeNameStr); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs index c4a90625c3..5579992d2b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/GodotDllImportResolver.cs @@ -6,9 +6,16 @@ using System.Runtime.InteropServices; namespace Godot.NativeInterop { - public static class GodotDllImportResolver + public class GodotDllImportResolver { - public static IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + private IntPtr _internalHandle; + + public GodotDllImportResolver(IntPtr internalHandle) + { + _internalHandle = internalHandle; + } + + public IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) { if (libraryName == "__Internal") { @@ -18,7 +25,7 @@ namespace Godot.NativeInterop } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - return Linux.dlopen(IntPtr.Zero, Linux.RTLD_LAZY); + return _internalHandle; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { @@ -40,18 +47,6 @@ namespace Godot.NativeInterop public static extern IntPtr dlopen(IntPtr path, int mode); } - private static class Linux - { - // libdl.so was resulting in DllNotFoundException, for some reason... - // libcoreclr.so should work with both CoreCLR and the .NET Core version of Mono. - private const string SystemLibrary = "libcoreclr.so"; - - public const int RTLD_LAZY = 1; - - [DllImport(SystemLibrary)] - public static extern IntPtr dlopen(IntPtr path, int mode); - } - private static class Win32 { private const string SystemLibrary = "Kernel32.dll"; -- cgit v1.2.3