Skip to content

Commit cd31a83

Browse files
authored
Merge pull request #741 from lilizoey/cleanup/script-instance-2
Cleanup some stuff mainly related to script instance
2 parents 0557d4c + 686b59d commit cd31a83

File tree

12 files changed

+604
-430
lines changed

12 files changed

+604
-430
lines changed

godot-core/src/builtin/callable.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ mod custom_callable {
432432
let a: &T = CallableUserdata::inner_from_raw(callable_userdata_a);
433433
let b: &T = CallableUserdata::inner_from_raw(callable_userdata_b);
434434

435-
(a == b) as sys::GDExtensionBool
435+
sys::conv::bool_to_sys(a == b)
436436
}
437437

438438
pub unsafe extern "C" fn rust_callable_to_string_display<T: fmt::Display>(
@@ -444,7 +444,7 @@ mod custom_callable {
444444
let s = crate::builtin::GString::from(c.to_string());
445445

446446
s.move_into_string_ptr(r_out);
447-
*r_is_valid = true as sys::GDExtensionBool;
447+
*r_is_valid = sys::conv::SYS_TRUE;
448448
}
449449

450450
pub unsafe extern "C" fn rust_callable_to_string_named<F>(
@@ -455,6 +455,6 @@ mod custom_callable {
455455
let w: &mut FnWrapper<F> = CallableUserdata::inner_from_raw(callable_userdata);
456456

457457
w.name.clone().move_into_string_ptr(r_out);
458-
*r_is_valid = true as sys::GDExtensionBool;
458+
*r_is_valid = sys::conv::SYS_TRUE;
459459
}
460460
}

godot-core/src/builtin/string/string_name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ impl From<&'static std::ffi::CStr> for StringName {
317317
sys::interface_fn!(string_name_new_with_latin1_chars)(
318318
ptr,
319319
c_str.as_ptr(),
320-
true as sys::GDExtensionBool, // p_is_static
320+
sys::conv::SYS_TRUE, // p_is_static
321321
)
322322
})
323323
};

godot-core/src/builtin/variant/mod.rs

+28
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,34 @@ impl Variant {
374374
// SAFETY: `variant_array` isn't null so it is safe to call `from_raw_parts_mut` on the pointer cast to `*mut Variant`.
375375
unsafe { std::slice::from_raw_parts_mut(variant_array, length) }
376376
}
377+
378+
/// Consumes self and turns it into a sys-ptr, should be used together with [`from_owned_var_sys`](Self::from_owned_var_sys).
379+
///
380+
/// This will leak memory unless `from_owned_var_sys` is called on the returned pointer.
381+
pub(crate) fn into_owned_var_sys(self) -> sys::GDExtensionVariantPtr {
382+
sys::static_assert_eq_size_align!(Variant, sys::types::OpaqueVariant);
383+
384+
let leaked = Box::into_raw(Box::new(self));
385+
leaked.cast()
386+
}
387+
388+
/// Creates a `Variant` from a sys-ptr without incrementing the refcount.
389+
///
390+
/// # Safety
391+
///
392+
/// * Must only be used on a pointer returned from a call to [`into_owned_var_sys`](Self::into_owned_var_sys).
393+
/// * Must not be called more than once on the same pointer.
394+
#[deny(unsafe_op_in_unsafe_fn)]
395+
pub(crate) unsafe fn from_owned_var_sys(ptr: sys::GDExtensionVariantPtr) -> Self {
396+
sys::static_assert_eq_size_align!(Variant, sys::types::OpaqueVariant);
397+
398+
let ptr = ptr.cast::<Self>();
399+
400+
// SAFETY: `ptr` was returned from a call to `into_owned_var_sys`, which means it was created by a call to
401+
// `Box::into_raw`, thus we can use `Box::from_raw` here. Additionally this is only called once on this pointer.
402+
let boxed = unsafe { Box::from_raw(ptr) };
403+
*boxed
404+
}
377405
}
378406

379407
impl ArrayElement for Variant {}

godot-core/src/meta/mod.rs

+103-35
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod traits;
1717
pub mod error;
1818
pub use class_name::ClassName;
1919
pub use godot_convert::{FromGodot, GodotConvert, ToGodot};
20+
use sys::conv::u32_to_usize;
2021
pub use traits::{ArrayElement, GodotType};
2122

2223
pub(crate) use crate::impl_godot_as_self;
@@ -241,50 +242,117 @@ pub struct MethodInfo {
241242
}
242243

243244
impl MethodInfo {
244-
/// Converts to the FFI type. Keep this object allocated while using that!
245-
///
246-
/// The struct returned by this function contains pointers into the fields of `self`. `self` should therefore not be dropped while the
247-
/// `sys::GDExtensionMethodInfo` is still in use.
245+
/// Consumes self and turns it into a `sys::GDExtensionMethodInfo`, should be used together with
246+
/// [`free_owned_method_sys`](Self::free_owned_method_sys).
248247
///
249-
/// This function also leaks memory that has to be cleaned up by the caller once it is no longer used. Specifically the `arguments` and
250-
/// `default_arguments` vectors have to be reconstructed from the pointer and length and then dropped/freed.
251-
///
252-
/// Each vector can be reconstructed with `Vec::from_raw_parts` since the pointers were created with `Vec::into_boxed_slice`, which
253-
/// guarantees that the vector capacity and length are equal.
254-
pub fn method_sys(&self) -> sys::GDExtensionMethodInfo {
248+
/// This will leak memory unless used together with `free_owned_method_sys`.
249+
pub fn into_owned_method_sys(self) -> sys::GDExtensionMethodInfo {
255250
use crate::obj::EngineBitfield as _;
256251

257-
let argument_count = self.arguments.len() as u32;
258-
let argument_vec = self
259-
.arguments
260-
.iter()
261-
.map(|arg| arg.property_sys())
262-
.collect::<Vec<_>>()
263-
.into_boxed_slice();
264-
265-
// SAFETY: dereferencing the new box pointer is fine as it is guaranteed to not be null
266-
let arguments = unsafe { (*Box::into_raw(argument_vec)).as_mut_ptr() };
267-
268-
let default_argument_count = self.default_arguments.len() as u32;
269-
let default_argument_vec = self
270-
.default_arguments
271-
.iter()
272-
.map(|arg| sys::SysPtr::force_mut(arg.var_sys()))
273-
.collect::<Vec<_>>()
274-
.into_boxed_slice();
275-
276-
// SAFETY: dereferencing the new box pointer is fine as it is guaranteed to not be null
277-
let default_arguments = unsafe { (*Box::into_raw(default_argument_vec)).as_mut_ptr() };
252+
// Destructure self to ensure all fields are used.
253+
let Self {
254+
id,
255+
method_name,
256+
// TODO: Do we need this?
257+
class_name: _class_name,
258+
return_type,
259+
arguments,
260+
default_arguments,
261+
flags,
262+
} = self;
263+
264+
let argument_count: u32 = arguments
265+
.len()
266+
.try_into()
267+
.expect("cannot have more than `u32::MAX` arguments");
268+
let arguments = arguments
269+
.into_iter()
270+
.map(|arg| arg.into_owned_property_sys())
271+
.collect::<Box<[_]>>();
272+
let arguments = Box::leak(arguments).as_mut_ptr();
273+
274+
let default_argument_count: u32 = default_arguments
275+
.len()
276+
.try_into()
277+
.expect("cannot have more than `u32::MAX` default arguments");
278+
let default_argument = default_arguments
279+
.into_iter()
280+
.map(|arg| arg.into_owned_var_sys())
281+
.collect::<Box<[_]>>();
282+
let default_arguments = Box::leak(default_argument).as_mut_ptr();
278283

279284
sys::GDExtensionMethodInfo {
280-
id: self.id,
281-
name: sys::SysPtr::force_mut(self.method_name.string_sys()),
282-
return_value: self.return_type.property_sys(),
285+
id,
286+
name: method_name.into_owned_string_sys(),
287+
return_value: return_type.into_owned_property_sys(),
283288
argument_count,
284289
arguments,
285290
default_argument_count,
286291
default_arguments,
287-
flags: u32::try_from(self.flags.ord()).expect("flags should be valid"),
292+
flags: flags.ord().try_into().expect("flags should be valid"),
293+
}
294+
}
295+
296+
/// Properly frees a `sys::GDExtensionMethodInfo` created by [`into_owned_method_sys`](Self::into_owned_method_sys).
297+
///
298+
/// # Safety
299+
///
300+
/// * Must only be used on a struct returned from a call to `into_owned_method_sys`, without modification.
301+
/// * Must not be called more than once on a `sys::GDExtensionMethodInfo` struct.
302+
#[deny(unsafe_op_in_unsafe_fn)]
303+
pub unsafe fn free_owned_method_sys(info: sys::GDExtensionMethodInfo) {
304+
// Destructure info to ensure all fields are used.
305+
let sys::GDExtensionMethodInfo {
306+
name,
307+
return_value,
308+
flags: _flags,
309+
id: _id,
310+
argument_count,
311+
arguments,
312+
default_argument_count,
313+
default_arguments,
314+
} = info;
315+
316+
// SAFETY: `name` is a pointer that was returned from `StringName::into_owned_string_sys`, and has not been freed before this.
317+
let _name = unsafe { StringName::from_owned_string_sys(name) };
318+
319+
// SAFETY: `return_value` is a pointer that was returned from `PropertyInfo::into_owned_property_sys`, and has not been freed before
320+
// this.
321+
unsafe { PropertyInfo::free_owned_property_sys(return_value) };
322+
323+
// SAFETY:
324+
// - `from_raw_parts_mut`: `arguments` comes from `as_mut_ptr()` on a mutable slice of length `argument_count`, and no other
325+
// accesses to the pointer happens for the lifetime of the slice.
326+
// - `Box::from_raw`: The slice was returned from a call to `Box::leak`, and we have ownership of the value behind this pointer.
327+
let arguments = unsafe {
328+
let slice = std::slice::from_raw_parts_mut(arguments, u32_to_usize(argument_count));
329+
330+
Box::from_raw(slice)
331+
};
332+
333+
for info in arguments.iter() {
334+
// SAFETY: These infos were originally created from a call to `PropertyInfo::into_owned_property_sys`, and this method
335+
// will not be called again on this pointer.
336+
unsafe { PropertyInfo::free_owned_property_sys(*info) }
337+
}
338+
339+
// SAFETY:
340+
// - `from_raw_parts_mut`: `default_arguments` comes from `as_mut_ptr()` on a mutable slice of length `default_argument_count`, and no
341+
// other accesses to the pointer happens for the lifetime of the slice.
342+
// - `Box::from_raw`: The slice was returned from a call to `Box::leak`, and we have ownership of the value behind this pointer.
343+
let default_arguments = unsafe {
344+
let slice = std::slice::from_raw_parts_mut(
345+
default_arguments,
346+
u32_to_usize(default_argument_count),
347+
);
348+
349+
Box::from_raw(slice)
350+
};
351+
352+
for variant in default_arguments.iter() {
353+
// SAFETY: These pointers were originally created from a call to `Variant::into_owned_var_sys`, and this method will not be
354+
// called again on this pointer.
355+
let _variant = unsafe { Variant::from_owned_var_sys(*variant) };
288356
}
289357
}
290358
}

0 commit comments

Comments
 (0)