diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/class_db.cpp | 4 | ||||
-rw-r--r-- | src/core/memory.cpp | 4 | ||||
-rw-r--r-- | src/godot.cpp | 57 |
3 files changed, 47 insertions, 18 deletions
diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 159c031..76abd21 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -77,7 +77,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf if (p_setter != String("")) { setter = get_method(p_class, p_setter); - ERR_FAIL_COND_MSG(!setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name))); + ERR_FAIL_NULL_MSG(setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name))); size_t exp_args = 1 + (p_index >= 0 ? 1 : 0); ERR_FAIL_COND_MSG((int)exp_args != setter->get_argument_count(), String("Setter method '{0}::{1}()' must take a single argument.").format(Array::make(p_class, p_setter))); @@ -86,7 +86,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf ERR_FAIL_COND_MSG(p_getter == String(""), String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name))); MethodBind *getter = get_method(p_class, p_getter); - ERR_FAIL_COND_MSG(!getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name))); + ERR_FAIL_NULL_MSG(getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name))); { size_t exp_args = 0 + (p_index >= 0 ? 1 : 0); ERR_FAIL_COND_MSG((int)exp_args != getter->get_argument_count(), String("Getter method '{0}::{1}()' must not take any argument.").format(Array::make(p_class, p_getter))); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 17b0696..80e71ec 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -42,7 +42,7 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { #endif void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0)); - ERR_FAIL_COND_V(!mem, nullptr); + ERR_FAIL_NULL_V(mem, nullptr); if (prepad) { uint8_t *s8 = (uint8_t *)mem; @@ -71,7 +71,7 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { if (prepad) { mem -= PAD_ALIGN; mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN); - ERR_FAIL_COND_V(!mem, nullptr); + ERR_FAIL_NULL_V(mem, nullptr); return mem + PAD_ALIGN; } else { return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes); diff --git a/src/godot.cpp b/src/godot.cpp index 96eae7c..0671221 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -34,6 +34,7 @@ #include <godot_cpp/classes/wrapped.hpp> #include <godot_cpp/core/class_db.hpp> #include <godot_cpp/core/memory.hpp> +#include <godot_cpp/core/version.hpp> #include <godot_cpp/variant/variant.hpp> #include <godot_cpp/core/error_macros.hpp> @@ -196,9 +197,15 @@ GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr; GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr; GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; -#define LOAD_PROC_ADDRESS(m_name, m_type) \ - internal::gdextension_interface_##m_name = (m_type)p_get_proc_address(#m_name); \ - ERR_FAIL_NULL_V_MSG(internal::gdextension_interface_##m_name, false, "Unable to load GDExtension interface function " #m_name "()") +#define ERR_PRINT_EARLY(m_msg) \ + internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false) + +#define LOAD_PROC_ADDRESS(m_name, m_type) \ + internal::gdextension_interface_##m_name = (m_type)p_get_proc_address(#m_name); \ + if (!internal::gdextension_interface_##m_name) { \ + ERR_PRINT_EARLY("Unable to load GDExtension interface function " #m_name "()"); \ + return false; \ + } // Partial definition of the legacy interface so we can detect it and show an error. typedef struct { @@ -221,14 +228,15 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge if (raw_interface[0] == 4 && raw_interface[1] == 0) { // Use the legacy interface only to give a nice error. LegacyGDExtensionInterface *legacy_interface = (LegacyGDExtensionInterface *)p_get_proc_address; - internal::gdextension_interface_print_error_with_message = (GDExtensionInterfacePrintErrorWithMessage)legacy_interface->print_error_with_message; - ERR_FAIL_V_MSG(false, "Cannot load a GDExtension built for Godot 4.1+ in Godot 4.0."); + internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)legacy_interface->print_error; + ERR_PRINT_EARLY("Cannot load a GDExtension built for Godot 4.1+ in Godot 4.0."); + return false; } - // Load the "print_error_with_message" function first (needed by the ERR_FAIL_NULL_V_MSG() macro). - internal::gdextension_interface_print_error_with_message = (GDExtensionInterfacePrintErrorWithMessage)p_get_proc_address("print_error_with_message"); - if (!internal::gdextension_interface_print_error_with_message) { - printf("ERROR: Unable to load GDExtension interface function print_error_with_message().\n"); + // Load the "print_error" function first (needed by the ERR_PRINT_EARLY() macro). + internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)p_get_proc_address("print_error"); + if (!internal::gdextension_interface_print_error) { + printf("ERROR: Unable to load GDExtension interface function print_error().\n"); return false; } @@ -237,10 +245,33 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge internal::token = p_library; LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion); + internal::gdextension_interface_get_godot_version(&internal::godot_version); + + // Check that godot-cpp was compiled using an extension_api.json older or at the + // same version as the Godot that is loading it. + bool compatible; + if (internal::godot_version.major != GODOT_VERSION_MAJOR) { + compatible = internal::godot_version.major > GODOT_VERSION_MAJOR; + } else if (internal::godot_version.minor != GODOT_VERSION_MINOR) { + compatible = internal::godot_version.minor > GODOT_VERSION_MINOR; + } else { + compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH; + } + if (!compatible) { + // We need to use snprintf() here because vformat() uses Variant, and we haven't loaded + // the GDExtension interface far enough to use Variants yet. + char msg[128]; + snprintf(msg, 128, "Cannot load a GDExtension built for Godot %d.%d.%d using an older version of Godot (%d.%d.%d).", + GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH, + internal::godot_version.major, internal::godot_version.minor, internal::godot_version.patch); + ERR_PRINT_EARLY(msg); + return false; + } + LOAD_PROC_ADDRESS(mem_alloc, GDExtensionInterfaceMemAlloc); LOAD_PROC_ADDRESS(mem_realloc, GDExtensionInterfaceMemRealloc); LOAD_PROC_ADDRESS(mem_free, GDExtensionInterfaceMemFree); - LOAD_PROC_ADDRESS(print_error, GDExtensionInterfacePrintError); + LOAD_PROC_ADDRESS(print_error_with_message, GDExtensionInterfacePrintErrorWithMessage); LOAD_PROC_ADDRESS(print_warning, GDExtensionInterfacePrintWarning); LOAD_PROC_ADDRESS(print_warning_with_message, GDExtensionInterfacePrintWarningWithMessage); LOAD_PROC_ADDRESS(print_script_error, GDExtensionInterfacePrintScriptError); @@ -376,14 +407,11 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin); LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin); - // Load the Godot version. - internal::gdextension_interface_get_godot_version(&internal::godot_version); - r_initialization->initialize = initialize_level; r_initialization->deinitialize = deinitialize_level; r_initialization->minimum_initialization_level = minimum_initialization_level; - ERR_FAIL_COND_V_MSG(init_callback == nullptr, false, "Initialization callback must be defined."); + ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); Variant::init_bindings(); register_engine_classes(); @@ -392,6 +420,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge } #undef LOAD_PROC_ADDRESS +#undef ERR_PRINT_EARLY void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) { ClassDB::current_level = p_level; |