GDExtension ~ Call GDScript function from C++ on a runtime spawned Node

Godot Version

4.2

Question

When writing a GDExtension project, I find I need the ability to call a function from GDScript on a Node that was created at run time. There could be 100s of these nodes spawned.

Like so : C++ Func --calls–> GDscript Func --returns–> C++ Func Consumes.

I fond this reddit post explaining a little bit about how

Ref script = ResourceLoader::load(“some_node.gd”, “Script”);
Object *obj = ClassDB::instance(script->get_instance_base_type());
obj->set_script(script.get_ref_ptr());
obj->call(“a_method”);

But what I need to understand is if I spawn a Node that has attached a GDExtension script onto it, I want to call a function in GDScript on that Node and get the return value for C++. The above reddit code doesn’t include such use case.

Thanks so much for any help!

1 Like

Objects that already have a script can be called in the same way that it was in the Reddit post’s explanation, but only the last line will apply. It doesn’t need its script to be set because it already has one.

I may be misunderstanding the post. Does this help? Could you elaborate if it doesn’t?

1 Like

Maybe it is simply that I don’t understand whats going on. I will create a model example to hopefully better illustrate the problem space.

Where GdStatusChecker.gd is attached to a node spawned during runtime and that node also has the SomeClass.cpp GDExtension class/node attached.

SomeClass.cpp

bool GetStatus(var1, var2)
{
   //Get a bool value to return based on GDscript function logic
   return call(“statusCheck”, var1, var2)
}

GdStatusChecker.gd

func statusCheck(var1, var2) -> bool:
       if var1 == var2:
           return true
       else:
         return false

The Node has data in GDScript that the CPP function wants to validate.

1 Like

I believe this should work. Does it not?

Due to using RefCounted the best solution was to pass the node with the script into the Extension.

MyExtension.h

class MyExtension : public RefCounted {

 private:
     Node3D *refNode;
  public:
      bool init_setup(Variant passInNode);

}

MyExtension.cpp

bool MyExtension ::init_setup(Variant passInNode)
{
    Node3D *passInNode = godot::Object::cast_to<godot::Node3D>(agentNode.operator Object *());
    if (passInNode== nullptr)
    {
        return false;
    }
    else
    {
        if (passInNode->has_method("someFunction"))
        {
            UtilityFunctions::print("MyNode: has function someFunction");
            refNode = passInNode;
             return true;
        }
        else
        {
             UtilityFunctions::print("MyNode: does not have function someFunction");
              return false;
        }
      
    }
}

void MyExtension ::use_gdScript_function() {
     Variant result = this->refNode->call("someFunction");
}

MyGDScript.gd

extends Node3D

var myExtension: RefCounted

func _ready():
	myExtension= MyExtension.new()
	myExtension.init_setup(self)