Skip to content

Commit 99da879

Browse files
TitanNanoBromeonlilizoey
committed
Implementation of Godot's GDExtensionScriptInstance
Co-authored-by: Jan Haller <[email protected]> Co-authored-by: Lili Zoey <[email protected]>
1 parent cc382c3 commit 99da879

File tree

9 files changed

+1220
-2
lines changed

9 files changed

+1220
-2
lines changed

godot-codegen/src/codegen_special_cases.rs

+3
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ const SELECTED_CLASSES: &[&str] = &[
158158
"ResourceLoader",
159159
"RigidBody2D",
160160
"SceneTree",
161+
"Script",
162+
"ScriptExtension",
163+
"ScriptLanguage",
161164
"Sprite2D",
162165
"SpriteFrames",
163166
"TextServer",

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

+60
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,63 @@ impl PropertyInfo {
273273
}
274274
}
275275
}
276+
277+
#[derive(Debug)]
278+
pub struct MethodInfo {
279+
pub id: i32,
280+
pub method_name: StringName,
281+
pub class_name: ClassName,
282+
pub return_type: PropertyInfo,
283+
pub arguments: Vec<PropertyInfo>,
284+
pub default_arguments: Vec<Variant>,
285+
pub flags: global::MethodFlags,
286+
}
287+
288+
impl MethodInfo {
289+
/// Converts to the FFI type. Keep this object allocated while using that!
290+
///
291+
/// The struct returned by this function contains pointers into the fields of `self`. `self` should therefore not be dropped while the
292+
/// [`sys::GDExtensionMethodInfo`] is still in use.
293+
///
294+
/// This function also leaks memory that has to be cleaned up by the caller once it is no longer used. Specifically the `arguments` and
295+
/// `default_arguments` vectors have to be reconstructed from the pointer and length and then dropped/freed.
296+
///
297+
/// Each vector can be reconstructed with `Vec::from_raw_parts` since the pointers were created with `Vec::into_boxed_slice`, which
298+
/// guarantees that the vector capacity and length are equal.
299+
pub fn method_sys(&self) -> sys::GDExtensionMethodInfo {
300+
use crate::obj::EngineEnum as _;
301+
302+
let argument_count = self.arguments.len() as u32;
303+
let argument_vec = self
304+
.arguments
305+
.iter()
306+
.map(|arg| arg.property_sys())
307+
.collect::<Vec<_>>()
308+
.into_boxed_slice();
309+
310+
// SAFETY: dereferencing the new box pointer is fine as it is guaranteed to not be null
311+
let arguments = unsafe { (*Box::into_raw(argument_vec)).as_mut_ptr() };
312+
313+
let default_argument_count = self.default_arguments.len() as u32;
314+
let default_argument_vec = self
315+
.default_arguments
316+
.iter()
317+
.map(|arg| arg.var_sys())
318+
.collect::<Vec<_>>()
319+
.into_boxed_slice();
320+
321+
// SAFETY: dereferencing the new box pointer is fine as it is guaranteed to not be null
322+
let default_arguments = unsafe { (*Box::into_raw(default_argument_vec)).as_mut_ptr() };
323+
324+
sys::GDExtensionMethodInfo {
325+
id: self.id,
326+
name: self.method_name.string_sys(),
327+
return_value: self.return_type.property_sys(),
328+
argument_count,
329+
arguments,
330+
default_argument_count,
331+
default_arguments,
332+
flags: u32::try_from(self.flags.ord()).expect("flags should be valid"),
333+
}
334+
}
335+
}

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ impl Variant {
236236
/// # Safety
237237
/// `variant_ptr_array` must be a valid pointer to an array of `length` variant pointers.
238238
/// The caller is responsible of keeping the backing storage alive while the unbounded references exist.
239-
#[cfg(since_api = "4.2")] // unused before
240239
pub(crate) unsafe fn unbounded_refs_from_sys<'a>(
241240
variant_ptr_array: *const sys::GDExtensionConstVariantPtr,
242241
length: usize,
@@ -253,6 +252,14 @@ impl Variant {
253252
pub(crate) fn ptr_from_sys_mut(variant_ptr: sys::GDExtensionVariantPtr) -> *mut Variant {
254253
variant_ptr as *mut Variant
255254
}
255+
256+
/// Move `self` into a system pointer. This transfers ownership and thus does not call the destructor.
257+
///
258+
/// # Safety
259+
/// `dst` must be a pointer to a [`Variant`] which is suitable for ffi with Godot.
260+
pub(crate) unsafe fn move_var_ptr(self, dst: sys::GDExtensionVariantPtr) {
261+
self.move_return_ptr(dst as *mut _, sys::PtrcallType::Standard);
262+
}
256263
}
257264

258265
// SAFETY:

godot-core/src/engine/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ pub use crate::gen::utilities;
1919
use crate::sys;
2020

2121
mod gfile;
22+
mod script_instance;
2223

2324
pub use gfile::{GFile, NotUniqueError};
25+
pub use script_instance::{create_script_instance, ScriptInstance};
2426

2527
/// Support for Godot _native structures_.
2628
///

0 commit comments

Comments
 (0)