Skip to content

InitHandle and NativeClass::new_instance() now refer to a global class registry to check if the class has been added. #737

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

Merged
merged 1 commit into from
May 11, 2021

Conversation

jacobsky
Copy link
Contributor

@jacobsky jacobsky commented May 9, 2021

This is related to issue #602 where and it allows the InitHandle struct and NativeClass trait to properly track whether a class has been added to the godot API.

This is just my first pass at a naming scheme, so if there is a preferred naming convention to go by or modifying the error messages, please let me know.

For the "class_registry", I decided to use the RwLock as there shouldn't be any need for locking after initialization. I thought this would be a performance be a minimal number of writes after initialization. This should lower the performance cost for reads after that point. The registry consists of a simple hash set as outlined in the Issue

For the NativeClass::new_instance() method, I chose to use a debug_assert!(), to give a more concrete error message when using a debug-build, but remove the additional check during instancing from Release builds.

If there are any other requests regarding this, I would be happy to make the necessary changes.

@Waridley
Copy link
Contributor

Waridley commented May 9, 2021

Could this also make it easier to support inheriting from another Rust NativeClass type? The engine will check if you pass the name of a class owned by the same gdnative library: https://github.com/godotengine/godot/blob/3.x/modules/gdnative/nativescript/godot_nativescript.cpp#L66

@jacobsky
Copy link
Contributor Author

@toasteater I went ahead and finished the changes that I was working on for the review in the latest commit 29fb8de please let me know if there's anything else that you'd like me to look into changing.

@jacobsky
Copy link
Contributor Author

@Waridley while that is not exactly the intent for this commit, it might be possible to extend that functionality. The main purpose of this commit is to help making it a bit more obvious whether a type is registered multiple-times as well as making it more obvious when a NativeScript is not registered at all.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thanks!

bors r+

support inheriting from another Rust NativeClass type

I'm not entirely sure how this would work on the Rust side. We'll need to look into what setting the base field actually means before we can even start to consider whether it would be useful. In any case, this is out of the scope of this PR.

bors bot added a commit that referenced this pull request May 10, 2021
737: InitHandle and NativeClass::new_instance() now refer to a global class registry to check if the class has been added. r=toasteater a=jacobsky

This is related to issue #602 where and it allows the `InitHandle` struct and `NativeClass` trait to properly track whether a class has been added to the godot API.

This is just my first pass at a naming scheme, so if there is a preferred naming convention to go by or modifying the error messages, please let me know.

For the "class_registry", I decided to use the RwLock as there shouldn't be any need for locking after initialization. I thought this would be a performance be a minimal number of writes after initialization. This should lower the performance cost for reads after that point. The registry consists of a simple hash set as outlined in the Issue

For the `NativeClass::new_instance()` method, I chose to use a debug_assert!(), to give a more concrete error message when using a debug-build, but remove the additional check during instancing from Release builds.

If there are any other requests regarding this, I would be happy to make the necessary changes.

Co-authored-by: Jacobsky <[email protected]>
@bors
Copy link
Contributor

bors bot commented May 10, 2021

Build failed:

@jacobsky
Copy link
Contributor Author

@toasteater looks like I still have some additional work to go. It looks like the changes crashed in the godot tests. Sorry about that. I ran the main test suite, but I must have missed running the godot tests. That's embarassing...

I'll work on resolving those test failures.

@jacobsky
Copy link
Contributor Author

I dug into the test cases a bit deeper and it looks like this is due to the test cases not actually calling an init callback. The easiest solution is likely to add a small section that allows it to bypass the check only in the test project. I tried by checking based on the feature "gd_test", but while this allows the checks in the test project to pass, the feature also appears to be active in the non-test projects.

@Waridley
Copy link
Contributor

@jacobsky Right, I'm not saying you should implement it now. The only reason I even mentioned it here was I want to make sure whatever we do doesn't make it harder to implement this, and just in case it seemed trivial to add I wanted you to be aware of it.

@ghost
Copy link

ghost commented May 10, 2021

I dug into the test cases a bit deeper and it looks like this is due to the test cases not actually calling an init callback.

That's weird. The functions sure do seem called in the code, and if we really didn't register the types, the tests should have fallen apart a long time ago. I think there's more to this problem that's worth investigation. We certainly don't want to hack around it by disabling the check in tests.

@ghost
Copy link

ghost commented May 10, 2021

That's said it's also not immediately obvious to me how the code can go wrong. It's short, and it contains no new unsafes. This is really weird.

@ghost ghost added the feature Adds functionality to the library label May 10, 2021
@jacobsky
Copy link
Contributor Author

@toasteater thank you for the insight! I'll keep digging a bit more into the test cases and see what I can find.

@jacobsky
Copy link
Contributor Author

I checked the various register functions as well as the lib.rs init function with print statements and it looks like it is never called. I was able to confirm this by also adding some panic!() macros into the init function and the panics never occurred. What is especially odd is that this should cause other failures.

I can also deduce that the macro is at least running since commenting it out causes the test to fail with the ERROR: initialize: Failed to obtain godot_gdnative_init symbol so I'm a bit stumped at the moment as to why the init() isn't being properly called in the tests.

After checking out the main difference, while it shouldn't cause any problems, it may be related to the gdscripts gdn.instance() call. I have a suspicion that it's not doing what we think it's supposed to do in that case. I tried modifying the GDNative library settings and none of them changed the behavior, the problem definitely looks like it's not doing exactly what we think it's doing.

The weirdest part is that not actually adding the classes should cause more issues in addition to what we're seeing. It's odd that it's only being revealed with this change.

@jacobsky
Copy link
Contributor Author

For completeness beefd87 includes a change that should allow the test to pass now. The cause was due to the lazy initialization of the godot_nativescript_init this was resolved by moving the check in class.rs::maybe_emplace() to later in the function to allow for godot to properly lazily load the library while also being available in rust.

…stered and give better error handling related to issue godot-rust#602.

Includes the feedback from PR#737 as well as the test failures that were found due to lazy initialization of nativescript
Changed error message with the that previously suggested (is the script registered?) now returns a more generic expectation
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's hope that this is working now!

bors r+

bors bot added a commit that referenced this pull request May 11, 2021
737: InitHandle and NativeClass::new_instance() now refer to a global class registry to check if the class has been added. r=toasteater a=jacobsky

This is related to issue #602 where and it allows the `InitHandle` struct and `NativeClass` trait to properly track whether a class has been added to the godot API.

This is just my first pass at a naming scheme, so if there is a preferred naming convention to go by or modifying the error messages, please let me know.

For the "class_registry", I decided to use the RwLock as there shouldn't be any need for locking after initialization. I thought this would be a performance be a minimal number of writes after initialization. This should lower the performance cost for reads after that point. The registry consists of a simple hash set as outlined in the Issue

For the `NativeClass::new_instance()` method, I chose to use a debug_assert!(), to give a more concrete error message when using a debug-build, but remove the additional check during instancing from Release builds.

If there are any other requests regarding this, I would be happy to make the necessary changes.

Co-authored-by: Jacobsky <[email protected]>
@bors
Copy link
Contributor

bors bot commented May 11, 2021

Build failed:

@ghost
Copy link

ghost commented May 11, 2021

Well there are some new lints in clippy. I'll fix that one.

@ghost
Copy link

ghost commented May 11, 2021

bors retry

@bors
Copy link
Contributor

bors bot commented May 11, 2021

Build succeeded:

@bors bors bot merged commit 8aecfba into godot-rust:master May 11, 2021
@jacobsky
Copy link
Contributor Author

@toasteater thank you for all the help! It was fun to make this addition.

@Bromeon Bromeon mentioned this pull request Sep 24, 2021
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants