module
Docs::O_CPP_BRIDGE_ARCHITECTURE
Overview
O. C++ GDExtension Loader Bridge Architecture
The LibGodot C++ GDExtension Loader Bridge (src/bridge/) provides the low-level,
native C-ABI execution bridge between the Godot Engine 4.8+ runtime and dynamically
compiled Crystal shared libraries (game.dll on Windows, game.so on Linux).
Architectural Invariants & Role
In Godot's GDExtension architecture, the engine expects a dynamic library that exports
crystal_library_init. While Crystal can produce dynamic libraries (--link-flags /DLL),
host-driven execution (where Godot is the parent host process) poses critical runtime challenges:
- Boehm GC Thread Registration: Foreign engine threads (Godot main thread, audio thread,
rendering thread, and WorkerThreadPool workers) allocating or accessing Crystal memory
crash with
EXCEPTION_ACCESS_VIOLATION(0xC0000005) unless registered with Boehm GC. - Headerless Flat C-ABI Interface: Crystal cannot consume complex C++ templates or
Godot C++ classes directly. The bridge translates Godot's C-API function table into flat,
predictable C-ABI data structures (
BridgeAPI,VariantArg,CrystalClassDesc). - Windows OS DLL File-Locking & Shadow Copying: On Windows,
LoadLibraryAlocks the DLL file on disk. The bridge creates unique timestamped shadow copies (game_loaded_<PID>_<TS>.dll) to leavebin/game.dllunlocked for continuous background compilation while the editor stays open. - Memory Pinning across Live Reloads: When Godot reloads a GDExtension, it calls
FreeLibraryon the extension DLL. Because Godot'sClassDBretains function pointers and instance userdata pointers, unmapping the bridge causes immediate access violations. The bridge pins itself in memory (GET_MODULE_HANDLE_EX_FLAG_PIN/RTLD_NODELETE) to remain permanent across reloads.
File Map Overview
| File | Role | Primary Functionality |
|---|---|---|
crystal_bridge.cpp |
Master Entry Point | Exports crystal_library_init, manages GDExtension lifecycle levels, and coordinates module unloading. |
common.hpp |
Platform & Crash Diagnostics | Win32/POSIX platform abstractions, crash interception, and backtrace generation to crash_dump.log. |
gdextension_api.hpp |
Function Pointer Table | Dynamically resolves and caches Godot C-API function pointers from p_get_proc_address. |
bridge_types.hpp |
C-ABI Data Contracts | Defines VariantArg, BridgeSignalArg, CrystalClassDesc, GenericExtensionInstance, and BridgeAPI. |
gc_support.hpp |
Boehm GC Thread Safety | Dynamically discovers gc.dll exports and registers foreign Godot threads with the garbage collector. |
editor_doc.hpp |
XML Help Harvester | Buffers XML class/property doc comments and flushes them into Godot's EditorHelp subsystem. |
dispatch_signals.hpp |
Method & Signal Dispatch | Variant marshaling, interned StringNames, CustomCallable signal wrappers, and dynamic vararg dispatch. |
extension_instance.hpp |
Instance Lifecycle | Instantiates Godot native base classes, binds Crystal objects, routes virtual methods, and handles property get/set. |
classdb_registry.hpp |
ClassDB Reflection | Registers custom classes, properties, signals, constants, and defers editor-only classes to EDITOR level. |
bridge_api.hpp |
Exported API Assembly | Populates global BridgeAPI table and defines exported C symbols for external binding. |
module_loader.hpp |
Dynamic Library Loader | Discovers candidate DLLs, creates timestamped shadow copies, preloads runtime DLLs, and calls crystal_godot_init. |
Deep Dive: Detailed File Mechanics
1. crystal_bridge.cpp
The master compilation translation unit and GDExtension library entry point.
crystal_library_init: Godot passesGDExtensionInterfaceGetProcAddress, a library handle pointer, and an output initialization structure.- Memory Pinning: On Windows, invokes
GetModuleHandleExAwithGET_MODULE_HANDLE_EX_FLAG_PIN. On Linux/POSIX, invokesdlopen(..., RTLD_NODELETE). This guarantees that Godot's internalFreeLibraryduring GDExtension reload does not unmap the loader bridge code while ClassDB retains pointers to it. - Lifecycle Levels:
GDEXTENSION_INITIALIZATION_CORE&SERVERS: Low-level pass-through.GDEXTENSION_INITIALIZATION_SCENE: Invokesinit_common_method_binds(), prints initialization banner, and invokesload_crystal_game_library()to loadgame.dlland register gameplay classes.GDEXTENSION_INITIALIZATION_EDITOR: Registers deferred editor classes (EditorPlugin,EditorSyntaxHighlighter) and flushes XML documentation intoEditorHelp.
- Deinitialization: Distinguishes engine shutdown from live reload. Invokes Crystal deinitialization callbacks (
g_library_deinit_callbacks) before tearing down classes.
2. common.hpp
Provides OS-level header imports, compiler visibility macros, and crash diagnostics:
GDE_EXPORT: Translates to__declspec(dllexport)on MSVC/MinGW, and__attribute__((visibility("default")))on GCC/Clang.- Vectored Exception Handling (VEH): On Windows, installs
custom_crash_handlerviaAddVectoredExceptionHandler. Upon intercepting anEXCEPTION_ACCESS_VIOLATION(0xC0000005) orSTATUS_HEAP_CORRUPTION(0xC0000374), it captures a 32-frame stack backtrace usingCaptureStackBackTrace, resolves module names and relative offsets viaGetModuleHandleExA, writescrash_dump.log, and outputs the diagnostic report to stderr and stdout.
3. gdextension_api.hpp
Manages the dynamic function pointer table required to interact with Godot's C-API:
- Stores static function pointers populated during
crystal_library_init(e.g.gd_string_name_new_with_utf8_chars,gd_variant_destroy,gd_classdb_register_extension_class6). - Contains engine logging utilities:
godot_log_print(Godot console print),godot_log_printerr(standard error),godot_log_error, andgodot_log_warning. These ensure diagnostics route to Godot's in-editor Output and Debugger panels as well as OS stdout.
4. bridge_types.hpp
Specifies the binary layout of all data exchanged between C++ and Crystal:
VariantArg: Tagged union supporting integers, floats, pointers, 64-bit instance IDs, and 4-component vector arrays (vec_val[4]).CrystalPropertyDesc: Describes an@Exportproperty (name, Godot type string, variant type enum, property hint, hint formatting string, and usage bitflags).CrystalSignalDesc: Defines signal signature metadata and argument types.CrystalClassDesc: Master metadata descriptor containing class flags (is_tool,has_process,has_physics_process, etc.) and host function pointers (create_instance,free_instance,call_virtual,set_property,get_property).PersistentClassDesc: Deep-copies string identifiers into invariant C++ standard library buffers (std::string), ensuring pointers passed to Godot'sClassDBremain valid across hot-reload cycles.BridgeAPI: Function pointer table passed directly tocrystal_godot_init(&g_bridge_api).
5. gc_support.hpp
Handles multi-threading and Boehm GC integration:
- Foreign Thread Registration: Godot utilizes background worker threads (
WorkerThreadPool), an audio server thread, and physics threads. If any of these threads allocate Crystal objects or invoke Crystal methods that trigger garbage collection, Boehm GC must know the thread's stack boundaries. - Dynamic Symbol Discovery: Dynamically resolves
GC_init,GC_allow_register_threads,GC_get_stack_base, andGC_register_my_threadfromgc.dllorlibgc.so. - Fast Thread-Local Cache: Uses
thread_local bool t_gc_thread_registeredso that once a thread is registered, subsequent entries incur zero overhead.
6. editor_doc.hpp
Provides Godot's in-editor F1 Help and hover tooltip documentation system:
- Collects doc comments harvested by Crystal macros into XML strings.
- Buffers XML documents until Godot reaches
GDEXTENSION_INITIALIZATION_EDITOR. - Invokes
gd_editor_help_load_xml_from_utf8_charsto register class and property documentation into Godot's offline documentation database.
7. dispatch_signals.hpp
Implements bidirectional method calling, Variant conversion, and CustomCallable signal dispatch:
- StringName Interning (
s_string_name_cache): Engine StringNames are interned for process lifetime. Destroying StringNames during runtime causes Godot's static string pool to complain withBUG: Unreferenced static string to 0. - Variant Unboxing: Features multi-tiered fallback in
bridge_object_from_variant:- Fast internal pointer access (
gd_variant_get_internal_ptr_object). - Standard type constructor unboxing (
gd_get_variant_to_type_constructor). - Safe 64-bit instance ID resolution (
gd_variant_get_object_instance_id+gd_object_get_instance_from_id).
- Fast internal pointer access (
- Signal Dispatch via
CustomCallable: Connects Godot signals to Crystal usingcallable_custom_create2(orcallable_custom_create). When Godot fires a signal,custom_callable_callconverts Variant arguments into an array ofVariantArgstructs and routes them directly to Crystal'ss_crystal_signal_callback.
8. extension_instance.hpp
Manages instance instantiation, virtual method routing, and property access:
generic_class_create: Resolves the root native Godot class (e.g.CharacterBody3D), invokesClassDBto allocate the C++ node, wraps it inGenericExtensionInstance, calls Crystal'screate_instancecallback, binds the instance viagd_object_set_instance, and auto-enables idle and physics processing.generic_class_recreate: Reconnects a Crystal instance wrapper to an existing native object during scene deserialization or reload.- Virtual Dispatch: Dispatches
_ready,_process(delta),_physics_process(delta),_enter_tree,_exit_tree, and_buildinto Crystal. Respects@toolannotations by checkingis_editor_active(). - Property Get/Set: Routes property modifications from the Godot Inspector into Crystal's
set_propertyandget_propertyhandlers.
9. classdb_registry.hpp
Handles registration with Godot's ClassDB:
bridge_register_class: Registers custom Crystal nodes, exported@Exportproperties, signals, and constants.- Inspector Property Groups: Maps property usage bitflags (64 for group, 256 for subgroup) to
gd_classdb_register_extension_class_property_groupandsubgroup. - Deferred Editor Classes: Classes inheriting from
EditorPlugin,EditorSyntaxHighlighter, orEditorDebuggerPlugincannot be registered atSCENElevel; they are automatically queued intog_deferred_editor_classesand registered when Godot reachesGDEXTENSION_INITIALIZATION_EDITOR.
10. bridge_api.hpp
Assembles and exports the C-ABI function pointer interface:
- Initializes the master
g_bridge_apistruct containing all bridge function pointers. - Exports external C symbols (
crystal_godot_print,crystal_bridge_get_api,crystal_bridge_set_reloading, etc.) withGDE_EXPORTfor foreign language interop or static linkage.
11. module_loader.hpp
Handles library discovery, runtime dependency loading, and Windows shadow copying:
- Candidate Search: Scans the bridge directory for
plugin.dll,game.dll, or custom addon DLLs. - Preloading Dependencies: On Windows, preloads runtime DLLs (
gc.dll,iconv-2.dll,pcre2-8.dll) before loading game modules. - Shadow Copy Mechanism: When running inside the Godot Editor (
bridge_should_use_shadow_copy()), copies the target library togame_loaded_<PID>_<TIMESTAMP>.dlland loads the shadow copy viaLoadLibraryExA(..., LOAD_WITH_ALTERED_SEARCH_PATH). - Cleanup:
cleanup_old_shadow_dllsscans for and deletes temporary shadow copies from previous closed sessions. - Handoff: Resolves
crystal_godot_initin the loaded library and invokes it, passing&g_bridge_api.
Defined in:
libgodot/docs/cpp_bridge.crClass Method Summary
-
.files : Array(String)
Returns the list of all C++ bridge files documented in this module
-
.invariants : Array(String)
Returns architectural invariants summary
Class Method Detail
Returns the list of all C++ bridge files documented in this module