Skip to content

Commit 60d50d2

Browse files
committed
Add module init; move symbols from macros + export
1 parent c90d7b7 commit 60d50d2

File tree

12 files changed

+320
-304
lines changed

12 files changed

+320
-304
lines changed

gdnative-async/src/rt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use gdnative_bindings::Object;
44
use gdnative_core::object::SubClass;
55

66
use gdnative_core::core_types::{GodotError, Variant};
7-
use gdnative_core::export::InitHandle;
87
use gdnative_core::export::{Instance, RefInstance};
8+
use gdnative_core::init::InitHandle;
99
use gdnative_core::object::ownership::Shared;
1010
use gdnative_core::object::TRef;
1111

gdnative-core/src/export/export.rs

Lines changed: 5 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ use std::ptr;
4040
use crate::core_types::{GodotString, ToVariant, Variant};
4141
use crate::export::method::*;
4242
use crate::export::property::*;
43-
use crate::export::{class_registry, emplace};
44-
use crate::export::{user_data::UserData, NativeClass, NativeClassMethods};
45-
use crate::object::{GodotObject, NewRef, RawObject, TRef};
43+
use crate::export::NativeClass;
44+
use crate::object::NewRef;
4645
use crate::private::get_api;
4746

4847
//pub use self::method::{
@@ -65,180 +64,11 @@ pub trait Export: ToVariant {
6564
fn export_info(hint: Option<Self::Hint>) -> ExportInfo;
6665
}
6766

68-
/// A handle that can register new classes to the engine during initialization.
69-
///
70-
/// See [`godot_nativescript_init`](macro.godot_nativescript_init.html) and
71-
/// [`godot_init`](macro.godot_init.html).
72-
#[derive(Copy, Clone)]
73-
pub struct InitHandle {
74-
#[doc(hidden)]
75-
handle: *mut libc::c_void,
76-
}
77-
78-
impl InitHandle {
79-
#[doc(hidden)]
80-
#[inline]
81-
pub unsafe fn new(handle: *mut libc::c_void) -> Self {
82-
InitHandle { handle }
83-
}
84-
85-
/// Registers a new class to the engine.
86-
#[inline]
87-
pub fn add_class<C>(self)
88-
where
89-
C: NativeClassMethods,
90-
{
91-
self.add_maybe_tool_class::<C>(false)
92-
}
93-
94-
/// Registers a new tool class to the engine.
95-
#[inline]
96-
pub fn add_tool_class<C>(self)
97-
where
98-
C: NativeClassMethods,
99-
{
100-
self.add_maybe_tool_class::<C>(true)
101-
}
102-
103-
#[inline]
104-
fn add_maybe_tool_class<C>(self, is_tool: bool)
105-
where
106-
C: NativeClassMethods,
107-
{
108-
if !class_registry::register_class::<C>() {
109-
panic!(
110-
"`{type_name}` has already been registered",
111-
type_name = std::any::type_name::<C>()
112-
);
113-
}
114-
unsafe {
115-
let class_name = CString::new(C::class_name()).unwrap();
116-
let base_name = CString::new(C::Base::class_name()).unwrap();
117-
118-
let create = {
119-
unsafe extern "C" fn constructor<C: NativeClass>(
120-
this: *mut sys::godot_object,
121-
_method_data: *mut libc::c_void,
122-
) -> *mut libc::c_void {
123-
use std::panic::{self, AssertUnwindSafe};
124-
125-
let this = match ptr::NonNull::new(this) {
126-
Some(this) => this,
127-
None => {
128-
godot_error!(
129-
"gdnative-core: error constructing {}: owner pointer is null",
130-
C::class_name(),
131-
);
132-
133-
return ptr::null_mut();
134-
}
135-
};
136-
137-
let owner = match RawObject::<C::Base>::try_from_sys_ref(this) {
138-
Some(owner) => owner,
139-
None => {
140-
godot_error!(
141-
"gdnative-core: error constructing {}: incompatible owner type, expecting {}",
142-
C::class_name(),
143-
C::Base::class_name(),
144-
);
145-
return ptr::null_mut();
146-
}
147-
};
148-
149-
let val = match panic::catch_unwind(AssertUnwindSafe(|| {
150-
emplace::take()
151-
.unwrap_or_else(|| C::init(TRef::new(C::Base::cast_ref(owner))))
152-
})) {
153-
Ok(val) => val,
154-
Err(_) => {
155-
godot_error!(
156-
"gdnative-core: error constructing {}: constructor panicked",
157-
C::class_name(),
158-
);
159-
return ptr::null_mut();
160-
}
161-
};
162-
163-
let wrapper = C::UserData::new(val);
164-
C::UserData::into_user_data(wrapper) as *mut _
165-
}
166-
167-
sys::godot_instance_create_func {
168-
create_func: Some(constructor::<C>),
169-
method_data: ptr::null_mut(),
170-
free_func: None,
171-
}
172-
};
173-
174-
let destroy = {
175-
unsafe extern "C" fn destructor<C: NativeClass>(
176-
_this: *mut sys::godot_object,
177-
_method_data: *mut libc::c_void,
178-
user_data: *mut libc::c_void,
179-
) {
180-
if user_data.is_null() {
181-
godot_error!(
182-
"gdnative-core: user data pointer for {} is null (did the constructor fail?)",
183-
C::class_name(),
184-
);
185-
return;
186-
}
187-
188-
let wrapper = C::UserData::consume_user_data_unchecked(user_data);
189-
drop(wrapper)
190-
}
191-
192-
sys::godot_instance_destroy_func {
193-
destroy_func: Some(destructor::<C>),
194-
method_data: ptr::null_mut(),
195-
free_func: None,
196-
}
197-
};
198-
199-
if is_tool {
200-
(get_api().godot_nativescript_register_tool_class)(
201-
self.handle as *mut _,
202-
class_name.as_ptr() as *const _,
203-
base_name.as_ptr() as *const _,
204-
create,
205-
destroy,
206-
);
207-
} else {
208-
(get_api().godot_nativescript_register_class)(
209-
self.handle as *mut _,
210-
class_name.as_ptr() as *const _,
211-
base_name.as_ptr() as *const _,
212-
create,
213-
destroy,
214-
);
215-
}
216-
217-
(get_api().godot_nativescript_set_type_tag)(
218-
self.handle as *mut _,
219-
class_name.as_ptr() as *const _,
220-
crate::export::type_tag::create::<C>(),
221-
);
222-
223-
let builder = ClassBuilder {
224-
init_handle: self.handle,
225-
class_name,
226-
_marker: PhantomData,
227-
};
228-
229-
C::register_properties(&builder);
230-
231-
// register methods
232-
C::register(&builder);
233-
}
234-
}
235-
}
236-
23767
#[derive(Debug)]
23868
pub struct ClassBuilder<C> {
239-
pub(super) init_handle: *mut libc::c_void,
240-
pub(super) class_name: CString,
241-
_marker: PhantomData<C>,
69+
pub(crate) init_handle: *mut libc::c_void,
70+
pub(crate) class_name: CString,
71+
pub(crate) _marker: PhantomData<C>,
24272
}
24373

24474
impl<C: NativeClass> ClassBuilder<C> {

gdnative-core/src/export/macros.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
#[macro_export]
1717
macro_rules! godot_nativescript_init {
1818
() => {
19-
fn godot_nativescript_init_empty(_init: $crate::export::InitHandle) {}
19+
fn godot_nativescript_init_empty(_init: $crate::init::InitHandle) {}
2020
$crate::godot_nativescript_init!(godot_nativescript_init_empty);
2121
};
2222
($callback:ident) => {
2323
$crate::godot_nativescript_init!($callback as godot_nativescript_init);
2424
};
2525
(_ as $fn_name:ident) => {
26-
fn godot_nativescript_init_empty(_init: $crate::export::InitHandle) {}
26+
fn godot_nativescript_init_empty(_init: $crate::init::InitHandle) {}
2727
$crate::godot_nativescript_init!(godot_nativescript_init_empty as $fn_name);
2828
};
2929
($callback:ident as $fn_name:ident) => {
@@ -36,7 +36,7 @@ macro_rules! godot_nativescript_init {
3636
}
3737

3838
let __result = ::std::panic::catch_unwind(|| {
39-
$callback($crate::export::InitHandle::new(handle));
39+
$callback($crate::init::InitHandle::new(handle));
4040
});
4141

4242
if __result.is_err() {
@@ -63,9 +63,9 @@ macro_rules! godot_nativescript_init {
6363
#[macro_export]
6464
macro_rules! godot_init {
6565
($callback:ident) => {
66-
$crate::godot_gdnative_init!();
67-
$crate::godot_nativescript_init!($callback);
68-
$crate::godot_gdnative_terminate!();
66+
$crate::init::godot_gdnative_init!();
67+
$crate::init::godot_nativescript_init!($callback);
68+
$crate::init::godot_gdnative_terminate!();
6969
};
7070
}
7171

gdnative-core/src/export/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
//! out the [`core_types`][crate::core_types] and [`object`][crate::object] modules, respectively.
1111
1212
mod class;
13-
mod emplace;
14-
#[allow(clippy::module_inception)] // same name as this module; TODO rename or spill out
1513
mod export;
14+
#[allow(clippy::module_inception)] // same name as this module; TODO rename or spill out
1615
mod macros;
1716
mod method;
1817
mod property;
1918

2019
pub(crate) mod class_registry;
20+
pub(crate) mod emplace;
2121
pub(crate) mod type_tag;
2222

2323
pub use class::*;

gdnative-core/src/init/info.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::core_types::GodotString;
2+
3+
/// Context for the [`godot_gdnative_init`][crate::init::godot_gdnative_init] callback.
4+
pub struct InitializeInfo {
5+
in_editor: bool,
6+
active_library_path: GodotString,
7+
options: *mut crate::sys::godot_gdnative_init_options,
8+
}
9+
10+
impl InitializeInfo {
11+
/// Returns true if the library is loaded in the Godot Editor.
12+
#[inline]
13+
pub fn in_editor(&self) -> bool {
14+
self.in_editor
15+
}
16+
17+
/// Returns a path to the library relative to the project.
18+
///
19+
/// Example: `res://../../target/debug/libhello_world.dylib`
20+
#[inline]
21+
pub fn active_library_path(&self) -> &GodotString {
22+
&self.active_library_path
23+
}
24+
25+
/// Internal interface.
26+
///
27+
/// # Safety
28+
///
29+
/// Will `panic!()` if options is NULL, UB if invalid.
30+
#[inline]
31+
#[doc(hidden)]
32+
pub unsafe fn new(options: *mut crate::sys::godot_gdnative_init_options) -> Self {
33+
assert!(!options.is_null(), "options were NULL");
34+
let crate::sys::godot_gdnative_init_options {
35+
in_editor,
36+
active_library_path,
37+
..
38+
} = *options;
39+
40+
let active_library_path = GodotString::clone_from_sys(*active_library_path);
41+
42+
Self {
43+
in_editor,
44+
active_library_path,
45+
options,
46+
}
47+
}
48+
49+
#[inline]
50+
pub fn report_loading_error<T>(&self, message: T)
51+
where
52+
T: std::fmt::Display,
53+
{
54+
let crate::sys::godot_gdnative_init_options {
55+
report_loading_error,
56+
gd_native_library,
57+
..
58+
} = unsafe { *self.options };
59+
60+
if let Some(report_loading_error_fn) = report_loading_error {
61+
// Add the trailing zero and convert Display => String
62+
let message = format!("{}\0", message);
63+
64+
// Convert to FFI compatible string
65+
let message = std::ffi::CStr::from_bytes_with_nul(message.as_bytes())
66+
.expect("message should not have a NULL");
67+
68+
unsafe {
69+
report_loading_error_fn(gd_native_library, message.as_ptr());
70+
}
71+
}
72+
}
73+
}
74+
75+
/// Context for the [`godot_gdnative_terminate`][crate::init::godot_gdnative_terminate] callback.
76+
pub struct TerminateInfo {
77+
in_editor: bool,
78+
}
79+
80+
impl TerminateInfo {
81+
#[inline]
82+
#[doc(hidden)] // avoids clippy warning: unsafe function's docs miss `# Safety` section
83+
pub unsafe fn new(options: *mut crate::sys::godot_gdnative_terminate_options) -> Self {
84+
assert!(!options.is_null(), "options were NULL");
85+
86+
let crate::sys::godot_gdnative_terminate_options { in_editor } = *options;
87+
88+
Self { in_editor }
89+
}
90+
91+
/// Returns `true` if the library is loaded in the Godot Editor.
92+
#[inline]
93+
pub fn in_editor(&self) -> bool {
94+
self.in_editor
95+
}
96+
}

0 commit comments

Comments
 (0)