Преглед на файлове

C#: Mostly fix hash of ManagedCallable

The hash can still change when reloading assemblies but in all other
cases the result should be correct.
RedworkDE преди 2 години
родител
ревизия
1cfc382fe8

+ 2 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs

@@ -11,6 +11,7 @@ namespace Godot.Bridge
         public delegate* unmanaged<IntPtr, godot_variant**, int, godot_bool*, void> SignalAwaiter_SignalCallback;
         public delegate* unmanaged<IntPtr, void*, godot_variant**, int, godot_variant*, void> DelegateUtils_InvokeWithVariantArgs;
         public delegate* unmanaged<IntPtr, IntPtr, godot_bool> DelegateUtils_DelegateEquals;
+        public delegate* unmanaged<IntPtr, int> DelegateUtils_DelegateHash;
         public delegate* unmanaged<IntPtr, godot_array*, godot_bool> DelegateUtils_TrySerializeDelegateWithGCHandle;
         public delegate* unmanaged<godot_array*, IntPtr*, godot_bool> DelegateUtils_TryDeserializeDelegateWithGCHandle;
         public delegate* unmanaged<void> ScriptManagerBridge_FrameCallback;
@@ -50,6 +51,7 @@ namespace Godot.Bridge
                 SignalAwaiter_SignalCallback = &SignalAwaiter.SignalCallback,
                 DelegateUtils_InvokeWithVariantArgs = &DelegateUtils.InvokeWithVariantArgs,
                 DelegateUtils_DelegateEquals = &DelegateUtils.DelegateEquals,
+                DelegateUtils_DelegateHash = &DelegateUtils.DelegateHash,
                 DelegateUtils_TrySerializeDelegateWithGCHandle = &DelegateUtils.TrySerializeDelegateWithGCHandle,
                 DelegateUtils_TryDeserializeDelegateWithGCHandle = &DelegateUtils.TryDeserializeDelegateWithGCHandle,
                 ScriptManagerBridge_FrameCallback = &ScriptManagerBridge.FrameCallback,

+ 15 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs

@@ -29,6 +29,21 @@ namespace Godot
             }
         }
 
+        [UnmanagedCallersOnly]
+        internal static int DelegateHash(IntPtr delegateGCHandle)
+        {
+            try
+            {
+                var @delegate = (Delegate?)GCHandle.FromIntPtr(delegateGCHandle).Target;
+                return @delegate?.GetHashCode() ?? 0;
+            }
+            catch (Exception e)
+            {
+                ExceptionUtils.LogException(e);
+                return 0;
+            }
+        }
+
         [UnmanagedCallersOnly]
         internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, void* trampoline,
             godot_variant** args, int argc, godot_variant* outRet)

+ 4 - 4
modules/mono/managed_callable.cpp

@@ -43,10 +43,10 @@ bool ManagedCallable::compare_equal(const CallableCustom *p_a, const CallableCus
 	const ManagedCallable *a = static_cast<const ManagedCallable *>(p_a);
 	const ManagedCallable *b = static_cast<const ManagedCallable *>(p_b);
 
+	if (a->delegate_handle.value == b->delegate_handle.value) {
+		return true;
+	}
 	if (!a->delegate_handle.value || !b->delegate_handle.value) {
-		if (!a->delegate_handle.value && !b->delegate_handle.value) {
-			return true;
-		}
 		return false;
 	}
 
@@ -63,7 +63,7 @@ bool ManagedCallable::compare_less(const CallableCustom *p_a, const CallableCust
 }
 
 uint32_t ManagedCallable::hash() const {
-	return hash_murmur3_one_64((uint64_t)delegate_handle.value);
+	return GDMonoCache::managed_callbacks.DelegateUtils_DelegateHash(delegate_handle);
 }
 
 String ManagedCallable::get_as_text() const {

+ 1 - 0
modules/mono/mono_gd/gd_mono_cache.cpp

@@ -52,6 +52,7 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
 	CHECK_CALLBACK_NOT_NULL(SignalAwaiter, SignalCallback);
 	CHECK_CALLBACK_NOT_NULL(DelegateUtils, InvokeWithVariantArgs);
 	CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateEquals);
+	CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateHash);
 	CHECK_CALLBACK_NOT_NULL(DelegateUtils, TrySerializeDelegateWithGCHandle);
 	CHECK_CALLBACK_NOT_NULL(DelegateUtils, TryDeserializeDelegateWithGCHandle);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, FrameCallback);

+ 2 - 0
modules/mono/mono_gd/gd_mono_cache.h

@@ -76,6 +76,7 @@ struct ManagedCallbacks {
 	using FuncSignalAwaiter_SignalCallback = void(GD_CLR_STDCALL *)(GCHandleIntPtr, const Variant **, int32_t, bool *);
 	using FuncDelegateUtils_InvokeWithVariantArgs = void(GD_CLR_STDCALL *)(GCHandleIntPtr, void *, const Variant **, int32_t, const Variant *);
 	using FuncDelegateUtils_DelegateEquals = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr);
+	using FuncDelegateUtils_DelegateHash = int32_t(GD_CLR_STDCALL *)(GCHandleIntPtr);
 	using FuncDelegateUtils_TrySerializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const Array *);
 	using FuncDelegateUtils_TryDeserializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(const Array *, GCHandleIntPtr *);
 	using FuncScriptManagerBridge_FrameCallback = void(GD_CLR_STDCALL *)();
@@ -109,6 +110,7 @@ struct ManagedCallbacks {
 	FuncSignalAwaiter_SignalCallback SignalAwaiter_SignalCallback;
 	FuncDelegateUtils_InvokeWithVariantArgs DelegateUtils_InvokeWithVariantArgs;
 	FuncDelegateUtils_DelegateEquals DelegateUtils_DelegateEquals;
+	FuncDelegateUtils_DelegateHash DelegateUtils_DelegateHash;
 	FuncDelegateUtils_TrySerializeDelegateWithGCHandle DelegateUtils_TrySerializeDelegateWithGCHandle;
 	FuncDelegateUtils_TryDeserializeDelegateWithGCHandle DelegateUtils_TryDeserializeDelegateWithGCHandle;
 	FuncScriptManagerBridge_FrameCallback ScriptManagerBridge_FrameCallback;