Closed ghost closed 1 year ago
Added the "help wanted" tag for ctor
/ linkme
platform support.
Update: iOS is now supported by inventory
.
In my game that uses godot-rust I've tried using the inventory
crate, and it seems to work pretty well.
This is what I came up with so far...
For every NativeClass I only need this bit of code to register it... (which could easily be turned into a derive macro to reduce boilerplate)
inventory::submit! {
AutoRegisterInfo::new("MyClass", 0, |handle| {
handle.add_class::<MyClass>();
})
}
Using a simple struct AutoRegisterInfo, that holds a closure for automatic class registration, and a priority for ordering purposes (the order of registrations seem to matter sometimes? I've had it crash on me before when the order was wrong)...
pub struct AutoRegisterInfo {
pub name: String, //Only used for debugging
pub priority: i32, //Use this to put registrations in the right order (higher = first)
pub register: fn(InitHandle),
}
impl AutoRegisterInfo {
pub fn new(name: &str, priority: i32, register: fn(InitHandle)) -> Self {
Self {
name: name.to_owned(),
priority,
register,
}
}
}
inventory::collect!(AutoRegisterInfo);
Then, in lib.rs
, I loop over all registrations and call them, ordered by priority...
godot_init!(init);
fn init(handle: InitHandle) {
for info in inventory::iter::<AutoRegisterInfo>
.into_iter()
.sorted_by_key(|info| -info.priority)
{
println!("Registering class {}", info.name);
(info.register)(handle);
}
}
By the way, as a con for inventory
, you mention "inventory currently uses ctor under the hood, which is life-before-main." I wonder, what does "life-before-main" mean exactly? And why is it a bad thing?
Both linkme
and inventory
have been archived, leaving room for speculation:
Update: unarchived, since the underlying rustc bug https://github.com/rust-lang/rust/pull/95604 was resolved.
Hello, does this improvement also applies to godot_test!
/ godot_itest!
?
They also need to be declared and invoked manually.
I'm planning to do something like that for GDExtension. Not sure about GDNative -- the added value at this point is relatively little, as so many tests already exist, and this would burden the library with more dependencies.
While using the bindings, one might create a new script type but forget to register it in
init
. It's a minor annoyance, but one that often leads to confusing errors when the new type is used, and is not handled by the compiler. Implementing automatic script registration improves usability and reduces the chances of runtime bugs.Provisions for automatic script registration seem to exist in the bindings for D, Kotlin, and Nim.
Currently, there are two crates in the Rust ecosystem that enable relatively easy automatic registration:
inventory
andlinkme
. The former is implemented through module initialization/teardown functions. The latter is based onlink_section
attributes. Both allow us to collect a list offn(&mut InitHandle) -> ()
pointers beforenativescript_init
and use them to automatically register all script types that derivedNativeClass
. The expected user-facing API is the same regardless of the implementation detail:Manual registration should still be possible for types with manual
NativeClass
impls:Implementation options
As mentioned before, there are two crates that can be used. They have slightly different pros/cons from each other, that are given here. In any case, this will be an implementation detail, and we should be able to swap implementations freely at a later time.
Both crates need some support with platform compatibility before they can be used in godot-rust.
inventory
Pros:
Cons:
inventory
currently usesctor
under the hood, which is life-before-main.ctor
lacks support for iOS (https://github.com/mmastrac/rust-ctor/issues/10). Implementation is supposedly very easy, but they need help testing.linkme
Pros:
Cons:
Considerations
Compatibility
It's possible to maintain compatibility with current manually registering code by making
InitHandle
track registered types, and ignore types that are already registered.Tool scripts
A
#[gdnative::tool]
attribute may be added for tool scripts, alongsidegdnative::register
.