跳到主要内容
知仓学习社ZHICANG

gdextension

Use when building native extensions for Godot — godot-cpp (C++) or gdext (Rust), binding classes, building, and GDScript/C# interop

不碰外部(只输出文字)无严重或高危命中jame581/GodotPrompter

它会碰到什么

扫了多少3 个文本文件,15 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

GDExtension

Run native C++ (or Rust) in Godot as a shared library without recompiling the engine. Use it for performance-critical code, wrapping existing C/C++ libraries, or language bindings.

> Related skills: csharp-godot for when C# is enough, gdscript-advanced for GDScript performance idioms first, godot-optimization for profiling before going native, addon-development for distributing the result, export-pipeline for shipping the binaries.


1. When to reach for GDExtension

Reach for GDScript or C# for almost all game logic. Choose GDExtension only when you genuinely need it:

  • Native speed in a hot loop that GDScript/C# can't keep up with (profile first — see godot-optimization).
  • Wrapping a C/C++ library you must call directly.
  • Building a language binding.

Contrast with C++ modules, which are compiled into the engine and therefore require shipping a custom engine binary. GDExtension's key advantage is that it runs against a stock Godot — you distribute just a shared library. It is "more complicated to use than GDScript and C#," so don't reach for it by default.

> ⚠️ Changed in Godot 4.7: Custom text servers are no longer a GDExtension use case — TextServer GDExtension build support was removed, so a custom TextServer must be compiled into the engine as a C++ module. See GH-117056.


2. Project & build setup

mkdir gdextension_example && cd gdextension_example
git init
# IMPORTANT: use the godot-cpp branch matching your target engine version (e.g. 4.3),
# not the literal "4.x".
git submodule add -b 4.3 https://github.com/godotengine/godot-cpp
cd godot-cpp && git submodule update --init && cd ..

Directory layout:

gdextension_example/
├── project/                # demo project to test the extension
│   └── bin/example.gdextension
├── godot-cpp/              # C++ bindings (submodule)
└── src/
    ├── register_types.{h,cpp}
    └── gdexample.{h,cpp}

Build with scons platform=<platform> (omit the platform to target the current one; default build is debug). The official SConstruct is a downloadable file from the C++ tutorial rather than hand-rolled here — follow godot-cpp's build docs. SCons is the official path; godot-cpp also supports CMake.

> Godot 4.7+: Upstream's reference GDExtension interface files (e.g. gdextension_interface.h) now live in the godot-headers repository instead of godot-cpp (GH-115401). godot-cpp consumes them from there, so the submodule workflow above is unchanged — this only matters if you vendor the raw interface headers directly (e.g. for a custom language binding).


3. Binding a class (C++)

Header (gdexample.h):

#pragma once
#include <godot_cpp/classes/sprite2d.hpp>

namespace godot {
class GDExample : public Sprite2D {
    GDCLASS(GDExample, Sprite2D)
private:
    double time_passed = 0.0;
    double amplitude = 10.0;
    double speed = 1.0;
protected:
    static void _bind_methods();
public:
    void _process(double delta) override;
    void set_amplitude(double p_amplitude);
    double get_amplitude() const;
    void set_speed(double p_speed);
    double get_speed() const;
};
}

Bindings (gdexample.cpp_bind_methods):

void GDExample::_bind_methods() {
    ClassDB::bind_method(D_METHOD("get_amplitude"), &GDExample::get_amplitude);
    ClassDB::bind_method(D_METHOD("set_amplitude", "p_amplitude"), &GDExample::set_amplitude);
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amplitude"), "set_amplitude", "get_amplitude");

    ClassDB::bind_method(D_METHOD("get_speed"), &GDExample::get_speed);
    ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &GDExample::set_speed);
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed", PROPERTY_HINT_RANGE, "0,20,0.01"),
                 "set_speed", "get_speed");

    ADD_SIGNAL(MethodInfo("position_changed",
               PropertyInfo(Variant::OBJECT, "node"),
               PropertyInfo(Variant::VECTOR2, "new_pos")));
}

The patterns:

  • GDCLASS(Class, Parent) — first line of every native class body; wires up the type into Godot's ClassDB.
  • ClassDB::bind_method(D_METHOD("name", "arg"), &Class::method) — exposes a method (and names its arguments) so GDScript/C#/the editor can call it.
  • ADD_PROPERTY(PropertyInfo(...), setter, getter) — registers an Inspector property; bind the getter and setter first, then reference them here by name.
  • PROPERTY_HINT_RANGE with "0,20,0.01" turns the Inspector field into a slider (min, max, step).
  • ADD_SIGNAL(MethodInfo("name", PropertyInfo(...), ...)) — declares a signal with typed arguments; emit it from code with emit_signal("position_changed", this, new_pos).

> ⚠️ Changed in Godot 4.7: The GDExtension interface functions object_cast_to and classdb_get_class_tag are deprecated in favor of is_class-based casts. Binding libraries (godot-cpp, gdext) handle this internally — but native code that calls these interface functions directly should migrate its cast paths. See GH-119254.


4. Entry point & the .gdextension file

Entry point (register_types.cpp):

void initialize_example_module(ModuleInitializationLevel p_level) {
    if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) return;
    GDREGISTER_CLASS(GDExample);
}
void uninitialize_example_module(ModuleInitializationLevel p_level) {
    if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) return;
}
extern "C" {
GDExtensionBool GDE_EXPORT example_library_init(
    GDExtensionInterfaceGetProcAddress p_get_proc_address,
    const GDExtensionClassLibraryPtr p_library,
    GDExtensionInitialization *r_initialization) {
    godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
    init_obj.register_initializer(initialize_example_module);
    init_obj.register_terminator(uninitialize_example_module);
    init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
    return init_obj.init();
}
}

The .gdextension file (project/bin/example.gdextension):

[configuration]
entry_symbol = "example_library_init"
compatibility_minimum = "4.3"
reloadable = true

[libraries]
macos.debug = "res://bin/libgdexample.macos.template_debug.dylib"
macos.release = "res://bin/libgdexample.macos.template_release.dylib"
windows.debug.x86_64 = "res://bin/gdexample.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/gdexample.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so"

The exported extern "C" symbol name must equal entry_symbol, or the extension won't load. Register classes with GDREGISTER_CLASS, gated on MODULE_INITIALIZATION_LEVEL_SCENE. The [libraries] keys are platform.feature.arch tags; template_debug / template_release distinguish build configs. Optional sections: [icons] (per-node editor icon) and [dependencies] (extra libs copied on export).

> Godot 4.7+: The raw GDExtension interface adds refcount-aware construction and registration entry points — classdb_construct_object3 and classdb_register_extension_class6 (GH-118214). Binding libraries built against 4.7 headers use them automatically; they only concern code that calls the interface directly.


5. Compatibility rules

Forward-but-not-backward. An extension targeting 4.2 works in 4.3, but one targeting 4.3 will not load in 4.2. Exception: extensions targeting 4.0 do not work in 4.1+.

  • The godot-cpp branch must match the engine version you build against.
  • reloadable = true hot reload works in debug builds only.
  • Set compatibility_minimum to the lowest engine version you actually support — too low and the extension fails to load at runtime.
  • Exported games need the matching template_release binaries present, or the native node type simply won't exist at runtime.

> ⚠️ Changed in Godot 4.7: Object.is_class() changed its class parameter type from String to StringName for performance. GDScript is unaffected and C# gained a compatibility method, but GDExtension binaries compiled against the old signature rely on the engine's compatibility mapping — rebuild against bindings matching your target version when updating to 4.7. See the 4.7 migration guide.


6. Using it from GDScript and C#

After building and placing the .gdextension file, the native class appears as a normal node type: bound properties show up in the Inspector (range hints become sliders) and signals appear in the Node dock.

GDScript

extends Node

func _ready():
    var node := GDExample.new()
    node.speed = 2.0
    node.position_changed.connect(_on_position_changed)
    add_child(node)

func _on_position_changed(node, new_pos):
    print("%s is now at %s" % [node.get_class(), new_pos])

C# Equivalent

using Godot;

public partial class Demo : Node
{
    public override void _Ready()
    {
        var node = new GDExample(); // The native class is available like any Godot type.
        node.Set("speed", 2.0);
        node.Connect("position_changed", Callable.From<Node, Vector2>(OnPositionChanged));
        AddChild(node);
    }

    private void OnPositionChanged(Node node, Vector2 newPos)
        => GD.Print($"{node.GetClass()} is now at {newPos}");
}

To get a strongly-typed C# wrapper you can ship a C# glue class, but the extension is fully usable via the dynamic Set / Connect / Call API shown above.

> Other languages & debugging: [Rust (gdext)](references/rust-gdext.md) · [Debugging native code](references/debugging-native.md)


Implementation Checklist

  • [ ] Confirmed native is actually needed (profiled; GDScript/C# insufficient — see godot-optimization)
  • [ ] godot-cpp submodule on the branch matching the target engine version
  • [ ] _bind_methods binds every exposed method/property/signal
  • [ ] entry_symbol in .gdextension matches the exported extern "C" symbol
  • [ ] compatibility_minimum set to the lowest engine version you support
  • [ ] [libraries] has correct paths for every shipped platform/arch (debug + release)
  • [ ] Release export includes the template_release binaries

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。