如何通过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
相关产品推荐
相关产品推荐

