-
-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gd<XXX>.bind() cause crash, with api-custom
feature in custom build godot.
#755
Comments
double-precision
feature with double precision build godot.double-precision
feature in double precision build godot.
exactly what godot version are you using, and what platform are you running on? i also notice you've enabled |
Latest godot
It is not necessary. i was removed |
https://github.com/godot-rust/gdext/blob/master/godot-core/src/registry/callbacks.rs#L67 fn create_rust_part_for_existing_godot_part<T, F>(
make_user_instance: F,
base_ptr: sys::GDExtensionObjectPtr,
) -> sys::GDExtensionClassInstancePtr
where
T: GodotClass,
F: FnOnce(Base<T::Base>) -> T,
{
let class_name = T::class_name();
//out!("create callback: {}", class_name.backing);
let base = unsafe { Base::from_sys(base_ptr) }; // <--- base_ptr https://github.com/godot-rust/gdext/blob/master/godot-core/src/obj/raw.rs#L426C66-L426C80 unsafe fn resolve_instance_ptr(&self) -> sys::GDExtensionClassInstancePtr {
if self.is_null() {
return ptr::null_mut();
}
let callbacks = crate::storage::nop_instance_callbacks();
let token = sys::get_library() as *mut std::ffi::c_void;
let binding = interface_fn!(object_get_instance_binding)(self.obj_sys(), token, &callbacks); // self.obj_sys()
but they have a different address in double-precision case |
double-precision
feature in double precision build godot.api-custom
feature in double precision build godot.
Update the title... this issue is cause by the even i just add |
api-custom
feature in double precision build godot.api-custom
feature in custom build godot.
That's weird, we build against Godot master in CI, so this should be tested. What os are you on? |
Windows 10 |
You mentioned just having the feature enabled reproduces it, however your example includes EditorPlugin etc. Can you come up with a truly minimal, reproducible example? If possible, post it inline here. Also, make sure you create a fresh Godot 4.2.2 project (with |
I tried to build a 4.2.2 rev of godot (
But when I build the latest master branch( This issues is probably caused by some version difference. I think it might have something related to prebuilt? what can I do to fix this? can I make custom prebuilts? |
Well, you cannot use a newer Godot version in See https://godot-rust.github.io/book/toolchain/godot-version.html and https://godot-rust.github.io/book/toolchain/compatibility.html. |
When I want to build a double-precision godot, which commit rev should I build? I tried adding the godot 4.2.2 But after building and running, it still prompts error
|
Did you read my links? 😉 You need |
@tommyZZM any update? |
i tried to build a godot 4.3 beta2 https://godotengine.org/article/dev-snapshot-godot-4-3-beta-2/#changelog
same crash still happen. what is latest compatible godot version or revision for |
Please do this. To avoid further back-and-forth, what I'm looking for is:
Sorry if this sounds annoying, but the reason why I ask is that we have a CI job that runs on Windows with a Godot double configuration (from nightly master), and it just passed a few minutes ago. We definitely use I need a way to reproduce this reliably and with as minimal setup as possible for the issue to stay open. Thanks a lot! |
Hello, I have tried some examples, and I attempted to run the try_case and bind methods in the enter_tree of both Parent and Child nodes. It seems to work during runtime. However, the same issue still appears in the example I initially provided. It might be that this problem only occurs with EditorInspectorPlugin, or it could be related to the editor itself. use godot::prelude::*;
use godot::classes::{
Node,
INode,
EditorInspectorPlugin,
EditorPlugin,
EditorProperty,
IEditorInspectorPlugin,
IEditorPlugin
};
struct IssueReproduceExtensionLibrary;
#[gdextension]
unsafe impl ExtensionLibrary for IssueReproduceExtensionLibrary {}
#[derive(GodotClass)]
#[class(base=Node)]
pub struct MyNodeParent {
pub base: Base<Node>,
pub count: i32,
}
#[godot_api]
impl INode for MyNodeParent {
// in editor created
fn init(base: Base<Node>) -> Self {
// godot_print!("init.. {}", !randInt!());
godot_print!("init..");
MyNodeParent {
base,
count: 1
}
}
fn enter_tree(&mut self) {
godot_print!("enter_tree..");
let child = Gd::from_init_fn(|base| {
MyNodeChild { base }
});
self.base_mut().add_child(child.upcast());
}
}
#[godot_api]
impl MyNodeParent {
#[func]
fn add(&mut self) {
godot_print!("add...");
self.count = self.count + 1
}
}
#[derive(GodotClass)]
#[class(base=Node)]
pub struct MyNodeChild {
pub base: Base<Node>
}
#[godot_api]
impl INode for MyNodeChild {
// in editor created
fn init(base: Base<Node>) -> Self {
// godot_print!("init.. {}", !randInt!());
godot_print!("init..");
MyNodeChild {
base
}
}
fn enter_tree(&mut self) {
let p = self.base_mut().get_parent().unwrap();
let p_class: String = p.clone().get_class().to_string();
godot_print!("[MyNodeChild]enter_tree.. parent is {}", p_class);
if p_class == "MyNodeParent" {
if let Ok(mut p_casted) = p.clone().try_cast::<MyNodeParent>() { // <-- this is OK
let mut b = p_casted.bind_mut();
b.add();
godot_print!("size is {}", b.count)
}
} else {
}
}
}
#[derive(GodotClass)]
#[class(tool, init, editor_plugin, base=EditorPlugin)]
pub struct MyEditorPlugin {
base: Base<EditorPlugin>,
inspector_: Option<Gd<EditorInspectorPlugin>>
}
#[godot_api]
impl IEditorPlugin for MyEditorPlugin {
fn enter_tree(&mut self) {
godot_print!("enter_tree");
// Perform typical plugin operations here.
let inspector_ = Gd::from_init_fn(|base| {
MyEdtiorInspectorPlugin {
base
}
}).clone();
self.inspector_ = Some(inspector_.clone().upcast());
self.base_mut().add_inspector_plugin(inspector_.clone().upcast());
}
fn exit_tree(&mut self) {
// Perform typical plugin operations here.
if let Some(ins) = self.inspector_.clone() {
self.base_mut().remove_inspector_plugin(ins.clone())
} else {
}
}
}
#[derive(GodotClass)]
#[class(tool, init, base=EditorInspectorPlugin)]
pub struct MyEdtiorInspectorPlugin{
base: Base<EditorInspectorPlugin>,
}
#[godot_api]
impl IEditorInspectorPlugin for MyEdtiorInspectorPlugin {
fn can_handle(&self, object: Gd<godot::classes::Object>) -> bool {
let a: String = object.clone().get_class().to_string();
let bool = a == "MyNodeParent";
bool
}
fn parse_begin(&mut self, object: Gd<godot::classes::Object>,) {
let a: String = object.clone().get_class().to_string();
godot_print!("get_calss is {}", a);
if let Ok(mut my_node_parent) = object.clone().try_cast::<MyNodeParent>() {
godot_print!("cast ok {}", a);
let my_node_parent_bind_mut = my_node_parent.bind(); // <-- error this line
// ERROR: godot-rust function call failed: MyEdtiorInspectorPlugin::parse_begin()
// Reason: [panic] Class test_case::MyNodeParent -- null instance; does the class h?
godot_print!("size is {}", my_node_parent_bind_mut.count) // <-- crash this line
}
}
} |
In the parse_begin method of EditorInspectorPlugin, when using custom-api, the object parameter seems unable to be correctly cast to the original object, resulting in a panic when calling bind. I tried printing the class name of the object, and it appears to be correct.
this should be the minial case yet It doesn’t crash like the Mesh object does, but the console outputs a panic when the bind method is executed during the To reproduce the panic, you have to select the use godot::prelude::*;
use godot::classes::{
Node,
INode,
EditorInspectorPlugin,
EditorPlugin,
EditorProperty,
IEditorInspectorPlugin,
IEditorPlugin
};
struct IssueReproduceExtensionLibrary;
#[gdextension]
unsafe impl ExtensionLibrary for IssueReproduceExtensionLibrary {}
#[derive(GodotClass)]
#[class(base=Node)]
pub struct MyNode {
pub base: Base<Node>,
#[export]
size: i32,
}
#[godot_api]
impl INode for MyNode {
// in editor created
fn init(base: Base<Node>) -> Self {
// godot_print!("init.. {}", !randInt!());
godot_print!("init..");
MyNode {
base,
size: 1024
}
}
}
#[derive(GodotClass)]
#[class(tool, init, editor_plugin, base=EditorPlugin)]
pub struct MyEditorPlugin {
base: Base<EditorPlugin>,
inspector_1: Option<Gd<EditorInspectorPlugin>>
}
#[godot_api]
impl IEditorPlugin for MyEditorPlugin {
fn enter_tree(&mut self) {
// Perform typical plugin operations here.
let inspector_1 = Gd::from_init_fn(|base| {
MyEdtiorInspectorPlugin {
base
}
}).clone();
self.inspector_1 = Some(inspector_1.clone().upcast());
self.base_mut().add_inspector_plugin(inspector_1.clone().upcast());
}
fn exit_tree(&mut self) {
// Perform typical plugin operations here.
if let Some(ins) = self.inspector_1.clone() {
self.base_mut().remove_inspector_plugin(ins.clone())
} else {
}
}
}
#[derive(GodotClass)]
#[class(tool, init, base=EditorInspectorPlugin)]
pub struct MyEdtiorInspectorPlugin{
base: Base<EditorInspectorPlugin>,
}
#[godot_api]
impl IEditorInspectorPlugin for MyEdtiorInspectorPlugin {
fn can_handle(&self, object: Gd<godot::classes::Object>) -> bool {
let a: String = object.get_class().to_string();
let bool = a == "MyNode";
bool
}
// panic when you select `MyNode` in editor
fn parse_begin(&mut self, object: Gd<godot::classes::Object>,) {
if let Ok(mesh) = object.try_cast::<MyNode>() {
// mesh.bind().size
// ERROR: godot-rust function call failed: MyEdtiorInspectorPlugin::parse_begin()
// Reason: [panic] Class test_case::MyNode -- null instance; does the class have a Godot creator function?
// at: godot_core::private::report_call_error (godot-core\src\private.rs:313)
godot_print!("size is {}", mesh.bind().size) // <-- crash this line
}
}
} To reproduce the issue:
You can use the repository I initially provided to follow these steps. case yet find in |
Thanks a lot. Since this is a bit more involved, it will take me some time until I can get around to try and reproduce it. In case you find a simpler way in the meantime (e.g. code only), let me know 🙂 |
I m trying to write a custom plugin for godot in double precision buildGd.bind() cause crash, with double-precision feature in(Latest godotdouble precision
build godot.master
branch)Update the title... this issue is cause by the api-custom feature..
even i only just add
api-custom
the case crash tooGd.bind() cause crash, with
api-custom
feature in custom build godot...But if same codes run in common build version it works fine
Maybe a minial reproduce case for this issue is here
https://github.com/tommyZZM/issue-cast-gd-pointer-crash-in-double-build/blob/main/rust/src/lib.rs#L95
logs
The text was updated successfully, but these errors were encountered: