Menu Share

Godot 4: GDExtension for C++ using CMake

by | Last Updated:
C / C++

With the release of the new Godot 4 version on 2023-03-01 the Godot engine the team behind it worked on many features. One of those features was the complete redesign of the GDNative bindings which I talked about some time ago in a blog post here. GDExtensions is the new successor to this GDNative bindings and you will find out that there are some major changes and some things that stay the same. Let’s dive in!

Table of Contents


For Godot there are quite a few languages available that you can “script” in. There is the official and recommended GDScript and the popular for game engines these days C#. But if you’re like me and you like it low-level you could go for developing directly in C++. This is also the language that the engine was written in and you could in fact develop a module for it.

C++ throug Godot Modules

Modules are one way to develop C++ for Godot. The engine itself is actually based on modularity and a lot of the functionality is split in modules. So they have also been made available for you to extend the engine. The modules though are limiting in one particular way. That is the fact that you need to compile the whole engine from scratch and you’re very much limited to their build system called scons.

This is not very robust or convinient for me and this is where GDExtension will take place.

So what is GDExtension

The GDExtension bindings allow you to build code that is meant to be used by Godot without recompiling. You essentially build your shared library in C++ (or any other language that has C++ bindings in fact) and then when you create your game you link to that extension. This is what I will be showing you how to do today.

GDExtension Project

So what I will do is a very simple CMake project where we’re going to build a shared library. This shared library will define a simple Movement class which will represent our custom node (script) that will handle simple movement. This will showcase the most basic things:

  • Registering our GDExtension
  • Registering our class as an extension to Node2D
  • Overriding Godot functions like process
  • Input handling
  • Defining properties like speed

The CMakeList.txt files

I use CMake since it is the most popular and well defined project configuration tool. I am aware that the godot team prefers scons but their decision is not the one that the general public would choose when starting a new project. CMake has the widest adoption by IDEs and companies and is actually really easy to work with. If you want to study more about CMake you can check out my course on the topic.

We will start by doing our root CMakeLists.txt file which should download the gdextension bindings and then link to them and add our library subdirectory CMakeLists.txt file. To do this I do the following setup:

cmake_minimum_required(VERSION 3.19)



        GIT_TAG godot-4.0-stable



I use FetchContent here to be able to link to a specific git tag which represents the bindings for the stable Godot 4.0 engine. If you’re reading this at a later date you could link to another tag. For this command to execute you would need to have git installed on your system. If you want to learn different ways to manage dependencies take a look at this post.

Now the way I have set this up is that we would have a subdirectory called gameplay which would define our library in the following way:


# Automatically pick up files added to src

# Add a dynamic library called gameplay - this builds gameplay.dll

target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(${PROJECT_NAME} PUBLIC godot::cpp)


Library Registration

Now we need a new source file that will register our library. Take a note here that most of hte things in the following code must be as-is or it will not work properly and you will have a hard time debugging it later. First I create a file called <root>/gameplay/src/gdextension_registration.cpp . This file will contain the following code:

#include <godot_cpp/godot.hpp>
#include <godot_cpp/core/class_db.hpp>

void register_gameplay_types(godot::ModuleInitializationLevel p_level) {
  if (p_level != godot::ModuleInitializationLevel::MODULE_INITIALIZATION_LEVEL_SCENE) {


void unregister_gameplay_types(godot::ModuleInitializationLevel p_level) {

extern "C" {

GDExtensionBool GDE_EXPORT gameplay_library_init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
  godot::GDExtensionBinding::InitObject init_object(p_interface, p_library, r_initialization);


  return init_object.init();


It is very important to note the function gameplay_library_init – you can call it whatever you like but it must take the same parameters, return GDExtensionBool, Have GDE_EXPORT before the name and most importantly have extern “C” around the whole function. Otherwise this function creates your gdextension init object and registers the above functions for adding types.

Defining & Implementing a Momvement Class

The next step in our jurney is to add two new files for defining our movement class – movement.h and movement.cpp. For simplicity I will not explain this too much and just have the well documented code pasted here:


#include <cstdint>
#include <godot_cpp/godot.hpp>
#include <godot_cpp/classes/node2d.hpp>

namespace godot {

class Movement : public Node2D {
  GDCLASS(Movement, Node2D)


  // Will be called by Godot when the class is registered
  // Use this to add properties to your class
  static void _bind_methods();

  void _process(double_t delta) override;

  // property setter
  void set_speed(float_t speed) {
	m_Speed = speed;

  // property getter
  [[nodiscard]] float_t get_speed() const {
	return m_Speed;

  Vector2 m_Velocity;

  // This will be a property later (look into _bind_methods)
  float_t m_Speed = 500.0f;
  void process_movement(double_t delta);



Now this is our class definition. The main thing here is that we define our variables that we will use privately as well as private methods. We also extend one method that you might have seen in typical GDScript called _process. This method will be called on every frame with the passed time in seconds (portion of the second).

I also want to showcase how you can define a property that is editable through the godot inspector. This property is speed. It doesn’t matter how we call it in our C++ code as you will notice later. We will pass to godot a string how we want it to be called in the editor. So lets see how this property is registered and how we handle the input events:

#include <movement.h>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/classes/input.hpp>

namespace godot {

void Movement::_process(double_t delta) {

void Movement::process_movement(double_t delta) {
  m_Velocity = Vector2(0.0f, 0.0f);
  Input& intutSingleton = *Input::get_singleton();

  if (intutSingleton.is_action_pressed("ui_right")) {
	m_Velocity.x += 1.0f;

  if (intutSingleton.is_action_pressed("ui_left")) {
	m_Velocity.x -= 1.0f;

  if (intutSingleton.is_action_pressed("ui_up")) {
	m_Velocity.y -= 1.0f;


  if (intutSingleton.is_action_pressed("ui_down")) {
	m_Velocity.y += 1.0f;

  set_position(get_position() + (m_Velocity * m_Speed * delta));

void Movement::_bind_methods() {
  UtilityFunctions::print("Binding methods");

  ClassDB::bind_method(D_METHOD("get_speed"), &Movement::get_speed);
  ClassDB::bind_method(D_METHOD("set_speed", "speed"), &Movement::set_speed);

  ADD_GROUP("Movement", "movement_");
  ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "movement_speed"), "set_speed", "get_speed");


You will notice this is a bit more verbose than GDScript. To define the property in _bind_methods you need to first bind both functions for getting and setting the value and then add the property. I also add the property to a group for nice styling.

For processing the movement I get the input manager which is a singleton in this case (I could also override the _input method for getting event callbacks) and then I check for some of the UI events. The idea is to move the node at some speed based on the passed frame time in the direction that was pressed.


Now the last part of this tutorial is to invoke the build. If you’re aware of how CMake works this will be very easy otherwise check my tutorial on the very basics of cmake. Basically we need to open up a terminal in the root directory of our project and run the command:

> cmake -S . -B ./build

Then to build it run:

> cmake --build ./build

After the build completes you will find your shared library inside “<root>/build/gameplay” and based on the platform you’re on it will be either or gamplay.dll or something like that. Remember this because we will need this file in the next section. You need to copy it in your godot project.

Godot Project

Next thing is to download Godot 4 from the official website and run it. You will be greeted with the default project wizard and you can create whatever project you like. Make sure to choose a 2D scene for this tutorial though when it starts.

Next step is to open the folder where your godot project was created and we will create a new resource folder for our gdextension. I call this folder gameplay to match my gameplay library and inside I add a directory called bin and a file called gameplay.gdextension. Inside the bin folder you will paste your shared library (gameplay.dll). Last thing is to open up the gameplay.gdextension with a notepad application and write the follwing code:

entry_symbol = "gameplay_library_init"

windows.debug.x86_64 = "bin/gameplay.dll"

Entry symbol here is that function I talked about when registering the library in the cpp code. That function that has to be wrapped in extern “C” you need to use now as and entry_symbol. The other thing is to set the libraries where you specify a path that is relative to the gameplay.gdextension file.

If you open up your Godot project freshly now you will be able to create a “Movement” node. I add the default icon on it and run the project. You can see how I set the scene up in the following video:


Well this is it! It isn’t as complicated as it seems in the beginning and with this knowledge you will be able to do some basic gameplay logic. This is close to how you would also work with Godot Modules which are directly embedded in the engine and this makes me very happy that GDExtension is here. It will allow us to make libraries for the Godot engine without actually having to recompile the whole engine.

Leave a comment