GDExtension referencing static functions and variables from seperate class failes to build

Hi!
New to Godot and the forum. Have some experience with c++, definitely not an expert in the field and maybe I’m missing something obvious here :sweat_smile:

Godot Version

godot 4.2.1 stable

Question

My test GDExtension code (based on the tutorial from the documentation, thwre is still the reference to Sprite2d there) fails to build when referencing static functions and variables from another class.
(using scons and VS Code)

#ifndef GDEXAMPLE_H
#define GDEXAMPLE_H

#include <godot_cpp/classes/sprite2d.hpp>

namespace godot {

class GDExample : public Sprite2D {
	GDCLASS(GDExample, Sprite2D)

protected:
	static void _bind_methods();

public:
	GDExample();
	~GDExample();

	void _process(double delta) override;
	int get_gridX();
	int get_gridY();
};

}

#endif
#include "gdexample.h"
#include "Grid/GridTest.h"
#include <godot_cpp/core/class_db.hpp>

using namespace godot;

void GDExample::_bind_methods() {
	ClassDB::bind_method(D_METHOD("process", "delta"), &GDExample::_process);
}

GDExample::GDExample() {
	GridTest::InitGrid();
}

GDExample::~GDExample() {}

void GDExample::_process(double delta) {
	GridTest::IterateGrid();
}

int GDExample::get_gridX()
{
	return GridTest::gridX;
}

int GDExample::get_gridY()
{
	return GridTest::gridY;
}
#ifndef GRIDTEST_H
#define GRIDTEST_H

class GridTest
{
public:
    static int gridX;
    static int gridY;

    static void InitGrid();
    static void IterateGrid();
};
#endif
#include "GridTest.h"

void GridTest::InitGrid()
{
    gridX = 107;
    gridY = 30;
}

void GridTest::IterateGrid()
{
    gridX += 1;
    gridY -= 1;
}
...
scons: done reading SConscript files.
scons: Building targets ...
scons: `godot-cpp\bin\libgodot-cpp.windows.template_debug.x86_64.lib' is up to date.
cl /Fosrc\gdexample.windows.template_debug.x86_64.obj /c src\gdexample.cpp /TP /std:c++17 /nologo /utf-8 /MT /O2 /DHOT_RELOAD_ENABLED /DTYPED_METHOD_BIND /DNOMINMAX /DWINDOWS_ENABLED /DDEBUG_ENABLED /DDEBUG_METHODS_ENABLED /DNDEBUG /D_HAS_EXCEPTIONS=0 /Igodot-cpp\gdextension /Igodot-cpp\include /Igodot-cpp\gen\include /Isrc
gdexample.cpp
link /nologo /WX /OPT:REF /OPT:NOICF /dll /out:demo\bin\libgdexample.windows.template_debug.x86_64.dll /implib:demo\bin\libgdexample.windows.template_debug.x86_64.lib godot-cpp\bin\libgodot-cpp.windows.template_debug.x86_64.lib src\gdexample.windows.template_debug.x86_64.obj src\register_types.windows.template_debug.x86_64.obj
   Creating library demo\bin\libgdexample.windows.template_debug.x86_64.lib and object demo\bin\libgdexample.windows.template_debug.x86_64.exp
gdexample.windows.template_debug.x86_64.obj : error LNK2019: unresolved external symbol "public: static void __cdecl GridTest::InitGrid(void)" (?InitGrid@GridTest@@SAXXZ) referenced in function "public: __cdecl godot::GDExample::GDExample(void)" (??0GDExample@godot@@QEAA@XZ)   
gdexample.windows.template_debug.x86_64.obj : error LNK2019: unresolved external symbol "public: static void __cdecl GridTest::IterateGrid(void)" (?IterateGrid@GridTest@@SAXXZ) referenced in function "public: virtual void __cdecl godot::GDExample::_process(double)" (?_process@GDExample@godot@@UEAAXN@Z)
gdexample.windows.template_debug.x86_64.obj : error LNK2019: unresolved external symbol "public: static int GridTest::gridX" (?gridX@GridTest@@2HA) referenced in function "public: int __cdecl godot::GDExample::get_gridX(void)" (?get_gridX@GDExample@godot@@QEAAHXZ)
gdexample.windows.template_debug.x86_64.obj : error LNK2019: unresolved external symbol "public: static int GridTest::gridY" (?gridY@GridTest@@2HA) referenced in function "public: int __cdecl godot::GDExample::get_gridY(void)" (?get_gridY@GDExample@godot@@QEAAHXZ)
demo\bin\libgdexample.windows.template_debug.x86_64.dll : fatal error LNK1120: 4 unresolved externals
scons: *** [demo\bin\libgdexample.windows.template_debug.x86_64.dll] Error 1120
scons: building terminated because of errors.

Any ideas what might be the cause? Did manage to build and test the example GDExtension code before running into this.

Thanks in advance for the help!

1 Like

I wasn’t able to reproduce the same errors, but I do have a few ideas.

What does your SConstruct file look like? It has to be tweaked to include more folders, like the one you have GridTest in. You can append the folder by inserting this under sources: sources.append(Glob("src/GridTest/*cpp"))

You may need to declare gridX and gridY in your GridTest.cpp file.

int GridTest::gridX = 0;
int GridTest::gridY = 0;

These lines can be added under your include in GridTest.cpp. For more on the difference between defining and initializing static member variables, there’s this.

2 Likes

Thanks @coder !
The Sconstruct was indeed missing the line:

sources.append(Glob("src/Grid/*.cpp"))

and the variables needed to be declared in the .cpp or be inlined.

scons is definitely new to me, is there a way to include all .cpp files in all subfolders of src?

1 Like

There is no built-in method for SCons to recursively search for .cpp files.

I haven’t tinkered with SCons as much as I was going to. The answers here have some code for custom recursion, but I haven’t tried them. Hierarchical builds are mentioned, but I haven’t tried them either. The append line seems to be the best method.

The demo in godot-cpp comes with a CMakeLists to use with CMake as an alternative to SCons. CMake does support recursion, but the CMakeLists will need changes. The engine uses SCons as a build system, so I use SCons.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.