Merge pull request #66674 from pkdawson/fix-callable-delegate

Fix C# delegate signal not disconnected when Object is destroyed
This commit is contained in:
Ignacio Roldán Etcheverry 2022-10-02 19:23:44 +02:00 committed by GitHub
commit abf473e2d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 13 additions and 8 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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,

View file

@ -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));
}

View file

@ -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);

View file

@ -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();
};