You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过GDExtension向Godot 4暴露函数、结构体与类型别名?

Godot 4 GDExtension对接C++的类型与函数暴露问题

我正在尝试使用Godot 4的GDExtension对接C++代码,但找不到合适的示例来实现不仅是类,还包括函数、结构体与类型别名的暴露,目前已编写如下代码:

register_types.cpp:

#include "register_types.h"
#include "../godot-cpp/gdextension/gdextension_interface.h"
#include "../godot-cpp/include/godot_cpp/core/class_db.hpp"
#include "../godot-cpp/include/godot_cpp/core/defs.hpp"
#include "../godot-cpp/include/godot_cpp/godot.hpp"
#include "cards.hpp"

void initialize_gdextension_types(godot::ModuleInitializationLevel p_level) {
  if (p_level != godot::MODULE_INITIALIZATION_LEVEL_CORE) {
    return;
  }
  // TODO: register my functions and structs
  // TODO: figure out how to do it
  godot::ObjectDB::register_object<Error>(); // <- no member named 'register_object' :)
}

void uninitialize_gdextension_types(godot::ModuleInitializationLevel p_level) {
  if (p_level != godot::MODULE_INITIALIZATION_LEVEL_CORE) {
    return;
  }
}

extern "C" {
// Initialization
// NOTE: I don't think we need to touch anything here
GDExtensionBool GDE_EXPORT
poker_utils_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address,
                         GDExtensionClassLibraryPtr p_library,
                         GDExtensionInitialization *r_initialization) {
  godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library,
                                                 r_initialization);
  init_obj.register_initializer(initialize_gdextension_types);
  init_obj.register_terminator(uninitialize_gdextension_types);
  init_obj.set_minimum_library_initialization_level(
      godot::MODULE_INITIALIZATION_LEVEL_CORE);

  return init_obj.init();
}
}

cards.hpp:

#ifndef CARDS_H_
#define CARDS_H_

#include <string>
#include <variant>

struct Error {
  std::string message;
};

using CardIndexResult = std::variant<int, Error>;

CardIndexResult getCardIndex(const std::string &card);

#endif // CARDS_H_

我尝试使用godot::ObjectDB::register_object<Error>();但无效,因此想请教:

  • 如何将Error结构体接入Godot?
  • 如何让getCardIndex可被Godot脚本调用?
  • 如何处理CardIndexResult类型别名?

后续尝试

我成功编译了以下代码:

// register_types.cpp
#include "register_types.h"
#include "../godot-cpp/gdextension/gdextension_interface.h"
#include "../godot-cpp/include/godot_cpp/core/class_db.hpp"
#include "../godot-cpp/include/godot_cpp/core/defs.hpp"
#include "../godot-cpp/include/godot_cpp/godot.hpp"

#include "deck.hpp"

void initialize_gdextension_types(godot::ModuleInitializationLevel p_level) {
  if (p_level != godot::MODULE_INITIALIZATION_LEVEL_CORE) {
    return;
  }
  godot::ClassDB::bind_static_method("@GlobalScope",
                                     godot::D_METHOD("get_deck"), &getDeck);
}

void uninitialize_gdextension_types(godot::ModuleInitializationLevel p_level) {
  if (p_level != godot::MODULE_INITIALIZATION_LEVEL_CORE) {
    return;
  }
}

extern "C" {
// Initialization
// NOTE: I don't think we need to touch anything here
GDExtensionBool GDE_EXPORT
poker_utils_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address,
                         GDExtensionClassLibraryPtr p_library,
                         GDExtensionInitialization *r_initialization) {
  godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library,
                                                 r_initialization);
  init_obj.register_initializer(initialize_gdextension_types);
  init_obj.register_terminator(uninitialize_gdextension_types);
  init_obj.set_minimum_library_initialization_level(
      godot::MODULE_INITIALIZATION_LEVEL_CORE);

  return init_obj.init();
}
}

deck.hpp文件定义如下:

#ifndef GODOT_PLUGIN_DECK_H_
#define GODOT_PLUGIN_DECK_H_

#include "../godot-cpp/include/godot_cpp/godot.hpp"
#include "../godot-cpp/include/godot_cpp/templates/vector.hpp"
#include "../godot-cpp/include/godot_cpp/variant/variant.hpp"

godot::PackedStringArray getDeck();

#endif // GODOT_PLUGIN_DECK_H_

该函数是对原函数的封装,实现如下:

// deck.cpp
#include "deck.hpp"
#include "../src/deck.hpp"

godot::PackedStringArray getDeck() {
  godot::PackedStringArray cards;
  auto deck = poker::getDeck();

  for (const auto &card : deck) {
    cards.push_back(godot::String(card.c_str()));
  }

  return cards;
};

问题:get_deck未在@GlobalScope中显示

扩展已被Godot识别并加载,但重启编辑器后,@GlobalScope文档中并未显示get_deck,不清楚问题所在。


问题解决

最终我通过封装类来容纳函数,在register_types.cpp的initialize_gdextension_types函数中添加godot::ClassDB::register_class<Poker>(),并在类中注册方法:

// poker.cpp
void Poker::_bind_methods() {
  godot::ClassDB::bind_static_method("Poker", godot::D_METHOD("get_deck"),
                                     &Poker::getDeck);
  godot::ClassDB::bind_static_method(
      "Poker", godot::D_METHOD("get_deck_shuffled"), &Poker::getDeckShuffled);
}

现在Godot可以识别该类并调用其方法!

内容的提问来源于stack exchange,提问作者shackra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:27:02