You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-08 12:40:44 +00:00
Merge pull request #96955 from Delsin-Yu/generator-based-CreateManagedForGodotObjectBinding
[.NET] Replace Reflection-Based implementation with Generated one in `CreateManagedForGodotObjectBinding`
This commit is contained in:
@@ -93,27 +93,15 @@ namespace Godot.Bridge
|
||||
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
|
||||
IntPtr godotObject)
|
||||
{
|
||||
// TODO: Optimize with source generators and delegate pointers.
|
||||
|
||||
try
|
||||
{
|
||||
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 = (GodotObject)FormatterServices.GetUninitializedObject(nativeType);
|
||||
var instance = Constructors.Invoke(nativeTypeNameStr, godotObject);
|
||||
|
||||
var ctor = nativeType.GetConstructor(
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
null, Type.EmptyTypes, null);
|
||||
|
||||
obj.NativePtr = godotObject;
|
||||
|
||||
_ = ctor!.Invoke(obj, null);
|
||||
|
||||
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(obj));
|
||||
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -308,66 +296,6 @@ namespace Godot.Bridge
|
||||
}
|
||||
}
|
||||
|
||||
private static Type? TypeGetProxyClass(string nativeTypeNameStr)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with a generated dictionary.
|
||||
|
||||
if (nativeTypeNameStr[0] == '_')
|
||||
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
|
||||
|
||||
Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr);
|
||||
}
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
|
||||
|
||||
if (editorAssembly != null)
|
||||
{
|
||||
wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr)
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var attr = type.GetCustomAttribute<GodotClassNameAttribute>();
|
||||
if (attr?.Name == nativeTypeNameStr)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
|
||||
|
||||
if (wrapperType != null && IsStatic(wrapperType))
|
||||
{
|
||||
// A static class means this is a Godot singleton class. Try to get the Instance proxy type.
|
||||
wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance");
|
||||
if (wrapperType == null)
|
||||
{
|
||||
// Otherwise, fallback to GodotObject.
|
||||
return typeof(GodotObject);
|
||||
}
|
||||
}
|
||||
|
||||
return wrapperType;
|
||||
}
|
||||
|
||||
// Called from GodotPlugins
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
public static void LookupScriptsInAssembly(Assembly assembly)
|
||||
|
||||
@@ -29,6 +29,17 @@ namespace Godot
|
||||
}
|
||||
}
|
||||
|
||||
internal GodotObject(IntPtr nativePtr) : this(false)
|
||||
{
|
||||
// NativePtr must be non-zero before calling ConstructAndInitialize to avoid invoking the constructor NativeCtor.
|
||||
// We don't want to invoke the constructor, because we already have a constructed instance in nativePtr.
|
||||
NativePtr = nativePtr;
|
||||
unsafe
|
||||
{
|
||||
ConstructAndInitialize(NativeCtor, NativeName, _cachedType, refCounted: false);
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe void ConstructAndInitialize(
|
||||
delegate* unmanaged<godot_bool, IntPtr> nativeCtor,
|
||||
StringName nativeName,
|
||||
|
||||
Reference in New Issue
Block a user