diff options
Diffstat (limited to 'core/extension/gdextension.cpp')
-rw-r--r-- | core/extension/gdextension.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index f158755a85..91038b9bdf 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -146,9 +146,11 @@ String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> class GDExtensionMethodBind : public MethodBind { GDExtensionClassMethodCall call_func; + GDExtensionClassMethodValidatedCall validated_call_func; GDExtensionClassMethodPtrCall ptrcall_func; void *method_userdata; bool vararg; + uint32_t argument_count; PropertyInfo return_value_info; GodotTypeInfo::Metadata return_value_metadata; List<PropertyInfo> arguments_info; @@ -191,6 +193,40 @@ public: r_error.expected = ce.expected; return ret; } + virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { + ERR_FAIL_COND_MSG(vararg, "Validated methods don't have ptrcall support. This is most likely an engine bug."); + GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance(); + + if (validated_call_func) { + // This is added here, but it's unlikely to be provided by most extensions. + validated_call_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), (GDExtensionVariantPtr)r_ret); + } else { +#if 1 + // Slow code-path, but works for the time being. + Callable::CallError ce; + call(p_object, p_args, argument_count, ce); +#else + // This is broken, because it needs more information to do the calling properly + + // If not provided, go via ptrcall, which is faster than resorting to regular call. + const void **argptrs = (const void **)alloca(argument_count * sizeof(void *)); + for (uint32_t i = 0; i < argument_count; i++) { + argptrs[i] = VariantInternal::get_opaque_pointer(p_args[i]); + } + + bool returns = true; + void *ret_opaque; + if (returns) { + ret_opaque = VariantInternal::get_opaque_pointer(r_ret); + } else { + ret_opaque = nullptr; // May be unnecessary as this is ignored, but just in case. + } + + ptrcall(p_object, argptrs, ret_opaque); +#endif + } + } + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); @@ -204,6 +240,7 @@ public: explicit GDExtensionMethodBind(const GDExtensionClassMethodInfo *p_method_info) { method_userdata = p_method_info->method_userdata; call_func = p_method_info->call_func; + validated_call_func = nullptr; ptrcall_func = p_method_info->ptrcall_func; set_name(*reinterpret_cast<StringName *>(p_method_info->name)); @@ -218,7 +255,7 @@ public: } set_hint_flags(p_method_info->method_flags); - + argument_count = p_method_info->argument_count; vararg = p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_VARARG; _set_returns(p_method_info->has_return_value); _set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST); |