GDExtension Lite
Automatically generated GDExtension bindings for C/C++
This is not meant to be a replacement for the godot-cpp project,
but rather an alternative for those who want the full API matching extension_api.json
in a C-compatible interface,
for example for creating bindings for other programming languages.
Features
- Easily embeddable in any project: include gdextension-lite.h, compile and link gdextension-lite-one.c and you're good to go
- Automatically generated from
extension_api.json
file, so new Godot APIs are added in a matter of regenerating the bindings - Bindings for all Godot classes, variant types, methods, operators, utility functions, enums, GDExtension interface functions
- Extra constructors with C strings for
String
,StringName
,NodePath
,Color
,godot_int
andgodot_float
GDCLEANUP
macro for declaring variables with automatic cleanup in C (compiler needs to support__attribute__((cleanup(...)))
, like GCC and clang)- Supports Godot 4.1+
- Faster compilation time than godot-cpp project
How to use
Implement your extension in C/C++:
// @file my-extension.c
// 1. Include gdextension-lite.h: the whole API is accessible through it
#include <gdextension-lite/gdextension-lite.h>
void initialize(void *userdata, GDExtensionInitializationLevel p_level);
void deinitialize(void *userdata, GDExtensionInitializationLevel p_level);
// 2. In your GDExtension entrypoint, call `gdextension_lite_initialize`
GDExtensionBool gdextension_entry(
const GDExtensionInterfaceGetProcAddress p_get_proc_address,
GDExtensionClassLibraryPtr p_library,
GDExtensionInitialization *r_initialization
) {
gdextension_lite_initialize(p_get_proc_address);
// setup initialize/deinitialize as usual
r_initialization->initialize = &initialize;
r_initialization->deinitialize = &deinitialize;
// return success as usual
return 1;
}
// 3. Use the bindings freely
void initialize(void *userdata, GDExtensionInitializationLevel p_level) {
if (p_level != GDEXTENSION_INITIALIZATION_SCENE) {
return;
}
// print("Hello from GDExtension Lite!")
{
godot_String msg = godot_String_new_with_latin1_chars("Hello from GDExtension Lite!");
godot_Variant msg_var = godot_Variant_new_with_String(&msg);
godot_print(&msg_var, NULL, 0);
// As always in C, you are responsible for freeing objects
godot_Variant_destroy(&msg_var);
godot_String_destroy(&msg);
}
// prints("OS.get_name() ==", OS.get_name())
{
// Use "GDCLEANUP(godot_TYPE)" for automatic variable cleanup at the end of scope
// (compiler needs to support `__attribute__((cleanup(...)))`, like GCC and clang)
GDCLEANUP(godot_StringName) singleton_name = godot_StringName_new_with_latin1_chars("OS");
// Objects are always used via pointers, no need for cleanup
// You may need to reference/unreference RefCounted instances, though
godot_OS *os = (godot_OS *) godot_global_get_singleton(&singleton_name);
GDCLEANUP(godot_String) os_name = godot_OS_get_name(os);
GDCLEANUP(godot_Variant) os_name_var = godot_Variant_new_with_String(&os_name);
GDCLEANUP(godot_String) msg = godot_String_new_with_latin1_chars("OS.get_name() ==");
GDCLEANUP(godot_Variant) msg_var = godot_Variant_new_with_String(&msg);
const godot_Variant *args[] = { &os_name_var };
godot_prints(&msg_var, args, 1);
}
}
void deinitialize(void *userdata, GDExtensionInitializationLevel p_level) {
// no-op
}
Now compile gdextension-lite-one.c
and link it to your own code.
Example SConstruct:
SharedLibrary(
[
'my-extension.c',
'path-to-gdextension-lite/gdextension-lite/gdextension-lite-one.c',
],
CFLAGS=["-O2", "-flto"],
)
We recommend compiling gdextension-lite-one.c
with -O2 -flto
flags to avoid linking all Godot functions, but rather link only the ones you actually use.
Sample code is also available at the sample folder.
Naming conventions
- Every type and function binding from Godot have the prefix
godot_
- Every GDExtension Lite function have the prefix
gdextension_lite_
- Constructors have the format
godot_<type name>_new
orgodot_<type name>_new_with_<arg1 type>_<arg2 type>...
- Destructors have the format
godot_<type name>_destroy
- Member getters have the format
godot_<type name>_get_<member name>
- Member setters have the format
godot_<type name>_set_<member name>
- Indexed getters have the format
godot_<type name>_indexed_get
- Indexed setters have the format
godot_<type name>_indexed_set
- Keyed getters have the format
godot_<type name>_keyed_get
- Keyed setters have the format
godot_<type name>_keyed_set
- Operators have the format
godot_<type name>_op_<operator name>
for unary operators andgodot_<type name>_op_<operator name>_<right-hand side type>
for binary operators - Methods have the format
godot_<type name>_<method name>
- Enumerators defined by classes have the format
godot_<type name>_<enum name>
- Godot utility functions have the format
godot_<function name>
- Variadic methods and utility functions expect argv/argc parameters.
Generating bindings
- Update the
extension_api.json
andgdextension_interface.h
files (depends on Godot 4 executable):make refresh-gdextension-api
- Generate the bindings files (depends on Python 3.10+):
make generate-bindings
- Generate the distribution
build/gdextension-lite.zip
file with all headers:make dist