From b277322172ad930ec42da8f98f6a52f3944232ab Mon Sep 17 00:00:00 2001 From: DE YU <71481700+Delsin-Yu@users.noreply.github.com> Date: Thu, 12 Sep 2024 20:24:06 +0800 Subject: [PATCH] Add basic implementation of generated ctor for CreateManagedForGodotObjectBinding --- modules/mono/editor/bindings_generator.cpp | 53 ++++++++++++++++++- .../Core/Bridge/ScriptManagerBridge.cs | 16 +++--- .../Core/Bridge/ScriptManagerBridge.ctor.cs | 18 +++++++ .../GodotSharp/Core/GodotObject.base.cs | 2 + modules/mono/godotsharp_defs.h | 1 + 5 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.ctor.cs diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 2ec073e4fa41..a2c8d5c6c8cb 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -1737,6 +1737,51 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { compile_items.push_back(output_file); } + // Generate source file for builtin type constructor dictionary + + StringBuilder cs_builtin_ctors_content; + + cs_builtin_ctors_content.append("namespace " BINDINGS_NAMESPACE ";\n\n"); + cs_builtin_ctors_content.append("using System;\n" + "using System.Collections.Generic;\n" + "\n"); + cs_builtin_ctors_content.append("internal static class " BINDINGS_CLASS_CONSTRUCTOR "\n{"); + + cs_builtin_ctors_content.append(MEMBER_BEGIN "private static readonly Dictionary> BuiltinMethodConstructors;\n"); + + cs_builtin_ctors_content.append(MEMBER_BEGIN "public static GodotObject Invoke(string nativeTypeNameStr, IntPtr nativeObjectPtr)\n"); + cs_builtin_ctors_content.append(INDENT1 OPEN_BLOCK); + cs_builtin_ctors_content.append(INDENT2 "if (!BuiltinMethodConstructors.TryGetValue(nativeTypeNameStr, out var constructor))\n"); + cs_builtin_ctors_content.append(INDENT3 "throw new InvalidOperationException(\"Wrapper class not found for type: \" + nativeTypeNameStr);\n"); + cs_builtin_ctors_content.append(INDENT2 "return constructor(nativeObjectPtr);\n"); + cs_builtin_ctors_content.append(INDENT1 CLOSE_BLOCK); + + cs_builtin_ctors_content.append(MEMBER_BEGIN "static GodotObjectConstructors()\n"); + cs_builtin_ctors_content.append(INDENT1 OPEN_BLOCK); + cs_builtin_ctors_content.append(INDENT2 "BuiltinMethodConstructors = new();\n"); + + for (const KeyValue &E : obj_types) { + const TypeInterface &itype = E.value; + + if (!itype.is_instantiable) { + continue; + } + + cs_builtin_ctors_content.append(INDENT2 "BuiltinMethodConstructors.Add(\""); + cs_builtin_ctors_content.append(itype.name); + cs_builtin_ctors_content.append("\", " CS_PARAM_INSTANCE " => new "); + cs_builtin_ctors_content.append(itype.proxy_name); + cs_builtin_ctors_content.append("(" CS_PARAM_INSTANCE "));\n"); + } + + cs_builtin_ctors_content.append(INDENT1 CLOSE_BLOCK); + + cs_builtin_ctors_content.append(CLOSE_BLOCK); + + String constructors_file = path::join(base_gen_dir, BINDINGS_CLASS_CONSTRUCTOR ".cs"); + Error err = _save_file(constructors_file, cs_builtin_ctors_content); + compile_items.push_back(constructors_file); + // Generate native calls StringBuilder cs_icalls_content; @@ -1762,7 +1807,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { if (icall.editor_only) { continue; } - Error err = _generate_cs_native_calls(icall, cs_icalls_content); + err = _generate_cs_native_calls(icall, cs_icalls_content); if (err != OK) { return err; } @@ -1772,7 +1817,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { String internal_methods_file = path::join(base_gen_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); - Error err = _save_file(internal_methods_file, cs_icalls_content); + err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) { return err; } @@ -2214,6 +2259,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(MEMBER_BEGIN "internal "); output.append(itype.proxy_name); output.append("(bool " CS_PARAM_MEMORYOWN ") : base(" CS_PARAM_MEMORYOWN ") { }\n"); + + output.append(MEMBER_BEGIN "internal "); + output.append(itype.proxy_name); + output.append("(IntPtr " CS_PARAM_INSTANCE ") : base(" CS_PARAM_INSTANCE ") { }\n"); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 901700067dfc..c7d51d9d1d3a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -101,19 +101,15 @@ internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_na 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 = (GodotObject)FormatterServices.GetUninitializedObject(nativeType); + Console.WriteLine($"CreateManaged: {nativeTypeNameStr}"); - var ctor = nativeType.GetConstructor( - BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, - null, Type.EmptyTypes, null); + // TODO: Singleton Types + // TODO: Editor Types + // TODO: NativeTypeNameStr that starts with Godot. - obj.NativePtr = godotObject; - - _ = ctor!.Invoke(obj, null); + var instance = GodotObjectConstructors.Invoke(nativeTypeNameStr, godotObject); - return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(obj)); + return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance)); } catch (Exception e) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.ctor.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.ctor.cs new file mode 100644 index 000000000000..1703baa02f2f --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.ctor.cs @@ -0,0 +1,18 @@ +// using System; +// using System.Collections.Generic; +// +// namespace Godot; +// +// // Generated +// internal static partial class GodotObjectConstructors +// { +// private static readonly Dictionary> BuiltinMethodConstructors; +// +// static GodotObjectConstructors() +// { +// BuiltinMethodConstructors = new(); +// BuiltinMethodConstructors.Add("", ptr => new GodotObject(ptr)); +// } +// +// public static partial GodotObject Invoke(string nativeTypeNameStr, IntPtr nativeObjectPtr) +// } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs index c094eaed7787..87cd99908a45 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs @@ -29,6 +29,8 @@ public GodotObject() : this(false) } } + internal GodotObject(IntPtr nativePtr) : this() => NativePtr = nativePtr; + internal unsafe void ConstructAndInitialize( delegate* unmanaged nativeCtor, StringName nativeName, diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index 08eeffc3db1a..81430f4bb717 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -38,6 +38,7 @@ #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor" #define TOOLS_ASM_NAME "GodotTools" +#define BINDINGS_CLASS_CONSTRUCTOR "GodotObjectConstructors" #define BINDINGS_CLASS_NATIVECALLS "NativeCalls" #define BINDINGS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls"