0 votes

Hey all,

I am considering using GDNative to help with performance issues with part of my code. However, I am handling some pretty complex data structures, and I'm wondering how feasible it will be for me to use a low level language like C or possibly Rust to work with those structures.

It would be difficult for me to go into detail on what exactly I'm doing, but a minimal example would be the following. Let's assume I have a script called data.gd with the following code:

var foo = 6
var bar = "baz"

And then I have another script called structure.gdwith the following code:

var data_preload = preload("res://data.gd")
var data_list = []

for i in range(0, 20):
    var tmp = data_preload.new()
    tmp.foo = i

data_list.append(tmp)

(I am aware that class_name is now a syntax. However, if possible, I'd like to accomplish this with the current preload() syntax.)

Now I want to make a GDNative module that might, for example, have a function that takes an instance of structure.gd as an argument, loops through data_list and sums up all of the foos, and then return the sum. What type should I give to the argument, what type should I give to the return type, and how should I access the properties of structure.gd or data.gd?

Any help is appreciated.

in Engine by (172 points)
edited by

1 Answer

+1 vote

I've recently did my first project in GDNative rust. What you describe is most definitely feasible. Internally, the source code is free to use any types. Only the methods that get binded need to have native godot types (except some primitive types like int, float and bool, which get casted automatically).
To some extend, it is possible to circumvent the godot api and access fields and methods of another gdnative object directly.

In your specific example, the function would look something like this (note: there are probably some errors):

use gdnative::*
#[export]
fn my_function(
        &mut self, mut _owner: gdnative::Node, 
        structure: gdnative::Variant
        ) -> i64 {

let func_name_get_data_list=GodotString::from_str("get_data_list");
if structure.has_method( function_name ) {
    let func_name_get_foo=GodotString::from_str("get_foo");
    let sum: i64 = 0;
    // data_list=structure.get_data_list()
    let data_list = structure.call( func_name_get_data_list , &[] ).to_array();
    for i in 0..data_list.len() {
          // sum+= data_list[i].get_foo()
          sum+=data_list.get( i ).unwrap().call( func_name_get_foo, &[] ).to_i64();
    }

sum
}
by (168 points)

Does godot automatically generate the getter functions (e.g. get_data_list())?
Are the .call()s required, or can I use the simpler lines above them?
Thanks for the response, it's already helped me a lot.

The getter/setter functions are automatically generated for the native types/classes from godot headers. You may have to declare them manually for custom scripts.
The .call() semantic in needed because it is not possible to infer custom types at compile time (rust is statically typed). The commented simpler lines are gdscript equivalents, to show what's happening.
You may notice that the input of the function is of type Variant. It is possible to cast this type into native types, but it has to be done manually. It's a price you pay for using compiled statically typed language. You are trading convenience for performance.

Forgot to check inbox for a while, didn't notice your reply. Thanks for putting the time into making such a detailed response. I've managed to significantly improve my performance with pure GDScript, but I may still use GDNative if I need the improvement. It seems like its definitely feasible, thanks for showing me how!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.