diff options
author | Ignacio Roldán Etcheverry <neikeq@users.noreply.github.com> | 2022-10-02 19:23:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-02 19:23:44 +0200 |
commit | abf473e2d022accdd5b7aa21d3e0b934b6ec0523 (patch) | |
tree | 72d3dcc6075b0980bf67c76ae6b5c40b230092dc | |
parent | e69b7083d45c5d8698508cce7086d361c4b1f44c (diff) | |
parent | 161f295f52d21dea940d7c06e5f83a14beefb4c9 (diff) |
Merge pull request #66674 from pkdawson/fix-callable-delegate
Fix C# delegate signal not disconnected when Object is destroyed
6 files changed, 13 insertions, 8 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs index 1b7f5158fd..bdedd2e87a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs @@ -72,7 +72,7 @@ namespace Godot /// <param name="delegate">Delegate method that will be called.</param> public Callable(Delegate @delegate) { - _target = null; + _target = @delegate?.Target as Object; _method = null; _delegate = @delegate; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 140fc167ba..76b186cd15 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -721,8 +721,9 @@ namespace Godot.NativeInterop if (p_managed_callable.Delegate != null) { var gcHandle = CustomGCHandle.AllocStrong(p_managed_callable.Delegate); + IntPtr objectPtr = p_managed_callable.Target != null ? Object.GetPtr(p_managed_callable.Target) : IntPtr.Zero; NativeFuncs.godotsharp_callable_new_with_delegate( - GCHandle.ToIntPtr(gcHandle), out godot_callable callable); + GCHandle.ToIntPtr(gcHandle), objectPtr, out godot_callable callable); return callable; } else diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index bd00611383..20ede9f0dd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -141,7 +141,7 @@ namespace Godot.NativeInterop public static partial void godotsharp_packed_string_array_add(ref godot_packed_string_array r_dest, in godot_string p_element); - public static partial void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, + public static partial void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, IntPtr p_object, out godot_callable r_callable); internal static partial godot_bool godotsharp_callable_get_data_for_marshalling(in godot_callable p_callable, diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 276701cdaa..2717b945f6 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -447,9 +447,10 @@ void godotsharp_packed_string_array_add(PackedStringArray *r_dest, const String r_dest->append(*p_element); } -void godotsharp_callable_new_with_delegate(GCHandleIntPtr p_delegate_handle, Callable *r_callable) { +void godotsharp_callable_new_with_delegate(GCHandleIntPtr p_delegate_handle, const Object *p_object, Callable *r_callable) { // TODO: Use pooling for ManagedCallable instances. - CallableCustom *managed_callable = memnew(ManagedCallable(p_delegate_handle)); + ObjectID objid = p_object ? p_object->get_instance_id() : ObjectID(); + CallableCustom *managed_callable = memnew(ManagedCallable(p_delegate_handle, objid)); memnew_placement(r_callable, Callable(managed_callable)); } diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp index 9305dc645a..0c2c533090 100644 --- a/modules/mono/managed_callable.cpp +++ b/modules/mono/managed_callable.cpp @@ -79,7 +79,9 @@ CallableCustom::CompareLessFunc ManagedCallable::get_compare_less_func() const { } ObjectID ManagedCallable::get_object() const { - // TODO: If the delegate target extends Godot.Object, use that instead! + if (object_id != ObjectID()) { + return object_id; + } return CSharpLanguage::get_singleton()->get_managed_callable_middleman()->get_instance_id(); } @@ -104,7 +106,7 @@ void ManagedCallable::release_delegate_handle() { // Why you do this clang-format... /* clang-format off */ -ManagedCallable::ManagedCallable(GCHandleIntPtr p_delegate_handle) : delegate_handle(p_delegate_handle) { +ManagedCallable::ManagedCallable(GCHandleIntPtr p_delegate_handle, ObjectID p_object_id) : delegate_handle(p_delegate_handle), object_id(p_object_id) { #ifdef GD_MONO_HOT_RELOAD { MutexLock lock(instances_mutex); diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h index aa3344f4d5..26cd164fb6 100644 --- a/modules/mono/managed_callable.h +++ b/modules/mono/managed_callable.h @@ -40,6 +40,7 @@ class ManagedCallable : public CallableCustom { friend class CSharpLanguage; GCHandleIntPtr delegate_handle; + ObjectID object_id; #ifdef GD_MONO_HOT_RELOAD SelfList<ManagedCallable> self_instance = this; @@ -66,7 +67,7 @@ public: void release_delegate_handle(); - ManagedCallable(GCHandleIntPtr p_delegate_handle); + ManagedCallable(GCHandleIntPtr p_delegate_handle, ObjectID p_object_id); ~ManagedCallable(); }; |