-
Notifications
You must be signed in to change notification settings - Fork 211
Description
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 and linkme. The former is implemented through module initialization/teardown functions. The latter is based on link_section attributes. Both allow us to collect a list of fn(&mut InitHandle) -> () pointers before nativescript_init and use them to automatically register all script types that derived NativeClass. The expected user-facing API is the same regardless of the implementation detail:
// The derive macro will automatically insert the relevant code.
#[derive(NativeClass)]
struct Foo;
// A separate attribute can be used for types with manual `NativeClass` impls.
#[gdnative::register]
struct Bar;
impl NativeClass for Bar {
/* - snip - */
}
// No callbacks necessary. It just works!
godot_gdnative_init!();
godot_nativescript_init!();
godot_gdnative_terminate!();Manual registration should still be possible for types with manual NativeClass impls:
struct ILikeBoilerplateCode;
impl NativeClass for ILikeBoilerplateCode {
/* - snip - */
}
fn init(handle: gdnative::init::InitHandle) {
handle.add_class::<ILikeBoilerplateCode>();
}
godot_gdnative_init!();
godot_nativescript_init!(init);
godot_gdnative_terminate!();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:
- Supports Android and iOS out of the box.
Cons:
inventorycurrently usesctorunder the hood, which is life-before-main.ctorlacks support for iOS (Support iOS dylib/executables mmastrac/rust-ctor#10). Implementation is supposedly very easy, but they need help testing.
linkme
Pros:
- Works at link time. No life-before-main or runtime cost.
Cons:
- No official support for both Android and iOS (no issues in repo). Implementation difficulty unknown.
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, alongside gdnative::register.