@@ -101,13 +101,10 @@ where
101
101
T::Mem::maybe_init_ref(&result);
102
102
result*/
103
103
104
- let result = unsafe {
104
+ unsafe {
105
105
let object_ptr = callbacks:: create :: < T > ( ptr:: null_mut ( ) ) ;
106
106
Gd :: from_obj_sys ( object_ptr)
107
- } ;
108
-
109
- T :: Mem :: maybe_init_ref ( & result) ;
110
- result
107
+ }
111
108
}
112
109
113
110
// FIXME use ```no_run instead of ```ignore, as soon as unit test #[cfg] mess is cleaned up
@@ -138,10 +135,7 @@ where
138
135
F : FnOnce ( crate :: obj:: Base < T :: Base > ) -> T ,
139
136
{
140
137
let object_ptr = callbacks:: create_custom ( init) ;
141
- let result = unsafe { Gd :: from_obj_sys ( object_ptr) } ;
142
-
143
- T :: Mem :: maybe_init_ref ( & result) ;
144
- result
138
+ unsafe { Gd :: from_obj_sys ( object_ptr) }
145
139
}
146
140
147
141
/// Hands out a guard for a shared borrow, through which the user instance can be read.
@@ -210,7 +204,7 @@ impl<T: GodotClass> Gd<T> {
210
204
None
211
205
} else {
212
206
// SAFETY: assumes that the returned GDExtensionObjectPtr is convertible to Object* (i.e. C++ upcast doesn't modify the pointer)
213
- let untyped = unsafe { Gd :: < engine:: Object > :: from_obj_sys ( ptr) . ready ( ) } ;
207
+ let untyped = unsafe { Gd :: < engine:: Object > :: from_obj_sys ( ptr) } ;
214
208
untyped. owned_cast :: < T > ( ) . ok ( )
215
209
}
216
210
}
@@ -277,14 +271,6 @@ impl<T: GodotClass> Gd<T> {
277
271
}
278
272
}
279
273
280
- /// Needed to initialize ref count -- must be explicitly invoked.
281
- ///
282
- /// Could be made part of FFI methods, but there are some edge cases where this is not intended.
283
- pub ( crate ) fn ready ( self ) -> Self {
284
- T :: Mem :: maybe_inc_ref ( & self ) ;
285
- self
286
- }
287
-
288
274
/// **Upcast:** convert into a smart pointer to a base class. Always succeeds.
289
275
///
290
276
/// Moves out of this value. If you want to create _another_ smart pointer instance,
@@ -366,7 +352,8 @@ impl<T: GodotClass> Gd<T> {
366
352
let class_tag = interface_fn ! ( classdb_get_class_tag) ( class_name. string_sys ( ) ) ;
367
353
let cast_object_ptr = interface_fn ! ( object_cast_to) ( self . obj_sys ( ) , class_tag) ;
368
354
369
- sys:: ptr_then ( cast_object_ptr, |ptr| Gd :: from_obj_sys ( ptr) )
355
+ // Create weak object, as ownership will be moved and reference-counter stays the same
356
+ sys:: ptr_then ( cast_object_ptr, |ptr| Gd :: from_obj_sys_weak ( ptr) )
370
357
}
371
358
372
359
pub ( crate ) fn as_ref_counted < R > ( & self , apply : impl Fn ( & mut engine:: RefCounted ) -> R ) -> R {
@@ -401,11 +388,30 @@ impl<T: GodotClass> Gd<T> {
401
388
ffi_methods ! {
402
389
type sys:: GDExtensionObjectPtr = Opaque ;
403
390
404
- fn from_obj_sys = from_sys;
405
- fn from_obj_sys_init = from_sys_init;
391
+ fn from_obj_sys_weak = from_sys;
406
392
fn obj_sys = sys;
407
393
fn write_obj_sys = write_sys;
408
394
}
395
+
396
+ /// Initializes this `Gd<T>` from the object pointer as a **strong ref**, meaning
397
+ /// it initializes/increments the reference counter and keeps the object alive.
398
+ ///
399
+ /// This is the default for most initializations from FFI. In cases where reference counter
400
+ /// should explicitly **not** be updated, [`Self::from_obj_sys_weak`] is available.
401
+ #[ doc( hidden) ]
402
+ pub unsafe fn from_obj_sys ( ptr : sys:: GDExtensionObjectPtr ) -> Self {
403
+ // Initialize reference counter, if needed
404
+ Self :: from_obj_sys_weak ( ptr) . with_inc_refcount ( )
405
+ }
406
+
407
+ /// Returns `self` but with initialized ref-count.
408
+ fn with_inc_refcount ( self ) -> Self {
409
+ // Note: use init_ref and not inc_ref, since this might be the first reference increment.
410
+ // Godot expects RefCounted::init_ref to be called instead of RefCounted::reference in that case.
411
+ // init_ref also doesn't hurt (except 1 possibly unnecessary check).
412
+ T :: Mem :: maybe_init_ref ( & self ) ;
413
+ self
414
+ }
409
415
}
410
416
411
417
/// _The methods in this impl block are only available for objects `T` that are manually managed,
@@ -501,7 +507,6 @@ impl<T: GodotClass> Gd<T> {
501
507
/// # Safety
502
508
/// `init_fn` must be a function that correctly handles a _type pointer_ pointing to an _object pointer_.
503
509
#[ doc( hidden) ]
504
- // TODO unsafe on init_fn instead of this fn?
505
510
pub unsafe fn from_sys_init_opt ( init_fn : impl FnOnce ( sys:: GDExtensionTypePtr ) ) -> Option < Self > {
506
511
// Note: see _call_native_mb_ret_obj() in godot-cpp, which does things quite different (e.g. querying the instance binding).
507
512
@@ -569,7 +574,7 @@ impl<T: GodotClass> Drop for Gd<T> {
569
574
impl < T : GodotClass > Share for Gd < T > {
570
575
fn share ( & self ) -> Self {
571
576
out ! ( "Gd::share" ) ;
572
- Self :: from_opaque ( self . opaque ) . ready ( )
577
+ Self :: from_opaque ( self . opaque ) . with_inc_refcount ( )
573
578
}
574
579
}
575
580
@@ -579,19 +584,23 @@ impl<T: GodotClass> Share for Gd<T> {
579
584
impl < T : GodotClass > FromVariant for Gd < T > {
580
585
fn try_from_variant ( variant : & Variant ) -> Result < Self , VariantConversionError > {
581
586
let result = unsafe {
582
- let result = Self :: from_sys_init ( |self_ptr| {
587
+ Self :: from_sys_init ( |self_ptr| {
583
588
let converter = sys:: builtin_fn!( object_from_variant) ;
584
589
converter ( self_ptr, variant. var_sys ( ) ) ;
585
- } ) ;
586
- result. ready ( )
590
+ } )
587
591
} ;
588
592
589
- Ok ( result)
593
+ // The conversion method `variant_to_object` does NOT increment the reference-count of the object; we need to do that manually.
594
+ // (This behaves differently in the opposite direction `object_to_variant`.)
595
+ Ok ( result. with_inc_refcount ( ) )
590
596
}
591
597
}
592
598
593
599
impl < T : GodotClass > ToVariant for Gd < T > {
594
600
fn to_variant ( & self ) -> Variant {
601
+ // The conversion method `object_to_variant` DOES increment the reference-count of the object; so nothing to do here.
602
+ // (This behaves differently in the opposite direction `variant_to_object`.)
603
+
595
604
unsafe {
596
605
Variant :: from_var_sys_init ( |variant_ptr| {
597
606
let converter = sys:: builtin_fn!( object_to_variant) ;
0 commit comments