Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Why Is It Designed This Way?

Design reasoningForeign ownershipRevision 637cef7

Why does Gd<T> exist instead of Box<T>?

Godot owns object identity and may use manual or reference-counted memory. Gd<T> is a typed view of an engine object pointer whose clone/drop behavior follows the class’s memory strategy. A Rust box would falsely claim sole allocation and destruction authority.

Why are Rust user classes dynamically borrowed?

Godot and GDScript can re-enter Rust through signals and virtual callbacks. Compile-time lifetimes cannot describe all foreign call sequences. bind and bind_mut therefore return guards enforcing shared/exclusive access at runtime, similar to RefCell but attached to engine object storage.

Why macros and code generation?

Godot publishes a large versioned API description. Generated engine classes and procedural macros keep function signatures, inheritance markers, registration, argument conversion, and virtual trampolines synchronized. Handwritten wrappers would multiply unsafe boilerplate and drift.

Why is inheritance represented with traits and composition?

Rust has no class inheritance. GodotClass::Base, Inherits<T>, generated deref behavior, and a stored Base<T> preserve the useful relationships while keeping the Rust user value structurally explicit.

Why are most objects main-thread-bound?

Godot’s scene tree and object lifecycle are not generally thread-safe. The safe API refuses to mark Gd<T> freely Send/Sync. Reviewed value operations and explicit thread-safe callables opt in separately.

Why catch panics at callbacks?

Rust unwinding across an extern "C" boundary is invalid. Trampolines catch and report panics, clean task/callback state, and return through the engine ABI.