Skip to content

Commit 66df8f4

Browse files
authored
Merge pull request #445 from lilizoey/fix/callable-refcount
Fix refcount of callables being erroneously decremented when received as argument
2 parents 4179fb4 + 546786a commit 66df8f4

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

godot-core/src/builtin/callable.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ impl Callable {
252252
pub fn as_inner(&self) -> inner::InnerCallable {
253253
inner::InnerCallable::from_outer(self)
254254
}
255+
256+
fn inc_ref(&self) {
257+
std::mem::forget(self.clone())
258+
}
255259
}
256260

257261
impl_builtin_traits! {
@@ -276,7 +280,18 @@ unsafe impl GodotFfi for Callable {
276280
sys::VariantType::Callable
277281
}
278282

279-
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque; .. }
283+
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
284+
fn from_sys;
285+
fn sys;
286+
fn from_sys_init;
287+
fn move_return_ptr;
288+
}
289+
290+
unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, _call_type: sys::PtrcallType) -> Self {
291+
let callable = Self::from_sys(ptr);
292+
callable.inc_ref();
293+
callable
294+
}
280295

281296
unsafe fn from_sys_init_default(init_fn: impl FnOnce(sys::GDExtensionTypePtr)) -> Self {
282297
let mut result = Self::invalid();

itest/godot/ManualFfiTests.gd

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,15 @@ func test_gd_self_reference_succeeds():
326326
gd_self_reference.update_internal_signal.connect(update_self_reference)
327327

328328
assert_eq(gd_self_reference.succeed_at_updating_internal_value(10), 10)
329+
330+
func sample_func():
331+
pass
332+
333+
func test_callable_refcount():
334+
var test_obj: CallableRefcountTest = CallableRefcountTest.new()
335+
for i in range(10):
336+
var method := Callable(self, "sample_func")
337+
test_obj.accept_callable(method)
338+
var method := Callable(self, "sample_func")
339+
assert(method.is_valid())
340+
test_obj.free()

itest/rust/src/builtin_tests/containers/callable_test.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@ fn callable_call_engine() {
127127
obj.free();
128128
}
129129

130+
// Testing https://github.com/godot-rust/gdext/issues/410
131+
132+
#[derive(GodotClass)]
133+
#[class(init, base = Node)]
134+
pub struct CallableRefcountTest {}
135+
136+
#[godot_api]
137+
impl CallableRefcountTest {
138+
#[func]
139+
fn accept_callable(&self, _call: Callable) {}
140+
}
141+
130142
// ----------------------------------------------------------------------------------------------------------------------------------------------
131143
// Tests and infrastructure for custom callables
132144

0 commit comments

Comments
 (0)