godot-rust / gdext

Rust bindings for Godot 4
https://mastodon.gamedev.place/@GodotRust
Mozilla Public License 2.0
3.08k stars 193 forks source link

dylib inside godot project breaks hot reaload #871

Open tbillington opened 2 months ago

tbillington commented 2 months ago

Hey, I'm getting errors in godot whenever I try to use hot reloading in Godot 4.3 (non-mono). I'm on 7634fe7 of gdext which is the latest as of now, with the api-4-3 feature enabled.

https://github.com/user-attachments/assets/6f05217d-87e5-4cce-8ad0-0b06c63b25ed

The error I get is related to ClassName it seems.

 /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/meta/class_name.rs:182.
    Context: failed to initialize GDExtension level `Scene`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  index out of bounds: the len is 0 but the index is 1
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to initialize GDExtension level `Editor`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  global lock for loaded classes poisoned; class registration or deregistration may have panicked
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to deinitialize GDExtension level `Editor`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  global lock for loaded classes poisoned; class registration or deregistration may have panicked
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to deinitialize GDExtension level `Scene`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  global lock for loaded classes poisoned; class registration or deregistration may have panicked
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to deinitialize GDExtension level `Servers`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  global lock for loaded classes poisoned; class registration or deregistration may have panicked
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to deinitialize GDExtension level `Core`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  global lock for loaded classes poisoned; class registration or deregistration may have panicked
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-ffi/src/binding/single_threaded.rs:75.

My code is just vanilla book starter

// lib.rs
mod player;

use godot::prelude::*;

struct MyExtension;

#[gdextension]
unsafe impl ExtensionLibrary for MyExtension {}

// player.rs
use godot::classes::{ISprite2D, Sprite2D};
use godot::prelude::*;

#[derive(GodotClass)]
#[class(base=Sprite2D)]
struct Player {
    speed: f64,
    angular_speed: f64,
    base: Base<Sprite2D>,
}

#[godot_api]
impl ISprite2D for Player {
    fn init(base: Base<Sprite2D>) -> Self {
        godot_print!("Hello, GD world!");
        Self {
            speed: 400.0,
            angular_speed: std::f64::consts::PI,
            base,
        }
    }

    fn physics_process(&mut self, delta: f64) {
        let radians = (self.angular_speed * delta) as f32;
        self.base_mut().rotate(radians);
    }
}

Rust 1.80

> rustc --version --verbose
rustc 1.80.1 (3f5fd8dd4 2024-08-06)
binary: rustc
commit-hash: 3f5fd8dd41153bc5fdca9427e9e05be2c767ba23
commit-date: 2024-08-06
host: aarch64-apple-darwin
release: 1.80.1
LLVM version: 18.1.7
Houtamelo commented 2 months ago

Do you have any classes marked with no_init? (In the #[class()] attribute)

tbillington commented 2 months ago

The included code is all I have in the project

zhouzhipeng commented 2 months ago

have you tried to restart godot editor?

tbillington commented 2 months ago

Restarting the editor allows the rust extension to function again until I do another cargo build, at which point it breaks and I receive the same error as I posted above.

tbillington commented 2 months ago

Ok, moving the location of the .dylib files out of the godot project directory allowed hot reload to work again.

I guess this is okay for development, but for builds the .dylib must be within the project for the res:// asset reference to work (at least according to the gdext book). I don't really want to switch back and forth the paths in .gdextension when I need to make a build.

Any thoughts on what I could do here?

Bromeon commented 1 month ago

I guess this is okay for development, but for builds the .dylib must be within the project for the res:// asset reference to work (at least according to the gdext book).

I'm actually not sure if the book advice still true. I recently exported a project (Windows Release) without changing anything in my paths, and it seemed to work.

Could you verify this with Godot 4.3?


About the error you get:

/Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/meta/class_name.rs:182.
    Context: failed to initialize GDExtension level `Scene`
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:378 - [panic]  index out of bounds: the len is 0 but the index is 1
  /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/private.rs:365 - Rust function panicked at /Users/choc/.cargo/git/checkouts/gdext-76630c89719e160c/7634fe7/godot-core/src/registry/class.rs:207.
    Context: failed to initialize GDExtension level `Editor`

This seems to happen here: https://github.com/godot-rust/gdext/blob/b39396bc22c85384d1176f972001d593232540a1/godot-core/src/meta/class_name.rs#L182

So classes are unloaded, but the cache still points to them. I wonder why this happens :thinking:

jgunzelman88 commented 1 week ago

I am running into the same problem. I did rename my lib and the file locations at some point after I registrered it with godot. @tbillington Did you re-name your extension? Maybe the cache is not getting updated from the original value.

Bromeon commented 1 week ago

Possibly related to https://github.com/godotengine/godot-cpp/issues/1573 and the now solved https://github.com/godotengine/godot-cpp/issues/1589. Would be interesting to see if it still occurs in last Godot nightly builds...

There's also https://github.com/godotengine/godot-cpp/pull/1594.