Add support for variadic method binds with the typed return. Sync headers.

pull/734/head
bruvzg 2022-03-29 14:44:07 +03:00
parent 5eb1c54116
commit 057a771fda
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
7 changed files with 4116 additions and 1020 deletions

View File

@ -1058,6 +1058,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
add_header(f"{snake_class_name}.cpp", result) add_header(f"{snake_class_name}.cpp", result)
result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>") result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
result.append(f"#include <godot_cpp/classes/global_constants_binds.hpp>")
result.append("") result.append("")
result.append(f"#include <godot_cpp/core/engine_ptrcall.hpp>") result.append(f"#include <godot_cpp/core/engine_ptrcall.hpp>")
result.append(f"#include <godot_cpp/core/error_macros.hpp>") result.append(f"#include <godot_cpp/core/error_macros.hpp>")
@ -1163,7 +1164,11 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append(method_call) result.append(method_call)
if vararg and ("return_value" in method and method["return_value"]["type"] != "void"): if vararg and ("return_value" in method and method["return_value"]["type"] != "void"):
result.append("\treturn ret;") return_type = method["return_value"]["type"].replace("enum::", "")
if return_type != "Variant":
result.append(f"\treturn VariantCaster<{return_type}>::cast(ret);")
else:
result.append("\treturn ret;")
result.append("}") result.append("}")
result.append("") result.append("")

File diff suppressed because it is too large Load Diff

View File

@ -205,10 +205,21 @@ typedef struct {
uint32_t usage; uint32_t usage;
} GDNativePropertyInfo; } GDNativePropertyInfo;
typedef struct {
const char *name;
GDNativePropertyInfo return_value;
uint32_t flags; // From GDNativeExtensionClassMethodFlags
int32_t id;
GDNativePropertyInfo *arguments;
uint32_t argument_count;
GDNativeVariantPtr default_arguments;
uint32_t default_argument_count;
} GDNativeMethodInfo;
typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list); typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
typedef const char *(*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out);
typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
@ -289,6 +300,79 @@ typedef struct {
GDNativeVariantPtr *default_arguments; GDNativeVariantPtr *default_arguments;
} GDNativeExtensionClassMethodInfo; } GDNativeExtensionClassMethodInfo;
/* SCRIPT INSTANCE EXTENSION */
typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation
typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid);
typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata);
typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
typedef const GDNativeMethodInfo *(*GDNativeExtensionScriptInstanceGetMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionScriptInstanceFreeMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeMethodInfo *p_list);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid);
typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetScript)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceIsPlaceholder)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef void *GDNativeExtensionScriptLanguagePtr;
typedef GDNativeExtensionScriptLanguagePtr (*GDNativeExtensionScriptInstanceGetLanguage)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef void (*GDNativeExtensionScriptInstanceFree)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef void *GDNativeScriptInstancePtr; // Pointer to ScriptInstance.
typedef struct {
GDNativeExtensionScriptInstanceSet set_func;
GDNativeExtensionScriptInstanceGet get_func;
GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func;
GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func;
GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func;
GDNativeExtensionScriptInstanceGetOwner get_owner_func;
GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func;
GDNativeExtensionScriptInstanceGetMethodList get_method_list_func;
GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func;
GDNativeExtensionScriptInstanceHasMethod has_method_func;
GDNativeExtensionScriptInstanceCall call_func;
GDNativeExtensionScriptInstanceNotification notification_func;
GDNativeExtensionScriptInstanceToString to_string_func;
GDNativeExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
GDNativeExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
GDNativeExtensionScriptInstanceGetScript get_script_func;
GDNativeExtensionScriptInstanceIsPlaceholder is_placeholder_func;
GDNativeExtensionScriptInstanceSet set_fallback_func;
GDNativeExtensionScriptInstanceGet get_fallback_func;
GDNativeExtensionScriptInstanceGetLanguage get_language_func;
GDNativeExtensionScriptInstanceFree free_func;
} GDNativeExtensionScriptInstanceInfo;
/* INTERFACE */ /* INTERFACE */
typedef struct { typedef struct {
@ -441,6 +525,10 @@ typedef struct {
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object); GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
/* SCRIPT INSTANCE */
GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data);
/* CLASSDB */ /* CLASSDB */
GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash); GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);

View File

@ -125,21 +125,19 @@ public:
virtual ~MethodBind(); virtual ~MethodBind();
}; };
template <class T> template <class Derived, class T, class R, bool should_returns>
class MethodBindVarArg : public MethodBind { class MethodBindVarArgBase : public MethodBind {
public:
typedef Variant (T::*NativeCall)(const Variant **, GDNativeInt, GDNativeCallError &);
protected: protected:
NativeCall call_method = nullptr; R(T::*method)
MethodInfo arguments; (const Variant **, GDNativeInt, GDNativeCallError &);
MethodInfo method_info;
public: public:
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
if (p_arg < 0) { if (p_arg < 0) {
return arguments.return_val; return _gen_return_type_info();
} else if (p_arg < arguments.arguments.size()) { } else if (p_arg < method_info.arguments.size()) {
return arguments.arguments[p_arg]; return method_info.arguments[p_arg];
} else { } else {
return PropertyInfo(Variant::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); return PropertyInfo(Variant::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
} }
@ -153,50 +151,98 @@ public:
return GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; return GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
} }
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const { virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const {
T *instance = static_cast<T *>(p_instance); ERR_FAIL(); // Can't call.
return (instance->*call_method)((const Variant **)p_args, p_argument_count, r_error);
} }
void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) { virtual bool is_const() const { return false; }
set_argument_count((int)p_info.arguments.size());
if (p_info.arguments.size()) { virtual bool is_vararg() const { return true; }
MethodBindVarArgBase(
R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
const MethodInfo &p_method_info,
bool p_return_nil_is_variant) :
method(p_method), method_info(p_method_info) {
set_argument_count(method_info.arguments.size());
if (method_info.arguments.size()) {
std::vector<std::string> names; std::vector<std::string> names;
names.reserve(p_info.arguments.size()); names.reserve(method_info.arguments.size());
for (int i = 0; i < p_info.arguments.size(); i++) { for (int i = 0; i < method_info.arguments.size(); i++) {
names.push_back(p_info.arguments[i].name); names.push_back(method_info.arguments[i].name);
} }
set_argument_names(names); set_argument_names(names);
} }
arguments = p_info;
if (p_return_nil_is_variant) { if (p_return_nil_is_variant) {
arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
} }
generate_argument_types((int)p_info.arguments.size()); generate_argument_types((int)method_info.arguments.size());
set_return(should_returns);
} }
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const { private:
ERR_FAIL(); // Can't call. GDNativePropertyInfo _gen_return_type_info() const {
} return reinterpret_cast<const Derived *>(this)->_gen_return_type_info_impl();
void set_method(NativeCall p_method) { call_method = p_method; }
virtual bool is_const() const { return false; }
virtual bool is_vararg() const { return true; }
MethodBindVarArg() {
set_return(true);
} }
}; };
template <class T> template <class T>
MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
MethodBindVarArg<T> *a = memnew(MethodBindVarArg<T>()); friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
a->set_method(p_method);
a->set_method_info(p_info, p_return_nil_is_variant); public:
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
(static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)((const Variant **)p_args, p_argument_count, r_error);
return {};
}
MethodBindVarArgT(
void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
const MethodInfo &p_method_info,
bool p_return_nil_is_variant) :
MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) {
}
private:
GDNativePropertyInfo _gen_return_type_info_impl() const {
return {};
}
};
template <class T>
MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
return a;
}
template <class T, class R>
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
public:
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
return (static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)((const Variant **)p_args, p_argument_count, r_error);
}
MethodBindVarArgTR(
R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
const MethodInfo &p_info,
bool p_return_nil_is_variant) :
MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) {
}
private:
GDNativePropertyInfo _gen_return_type_info_impl() const {
return GetTypeInfo<R>::get_class_info();
}
};
template <class T, class R>
MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static()); a->set_instance_class(T::get_class_static());
return a; return a;
} }

View File

@ -13,6 +13,8 @@ func _ready():
var ref = ExampleRef.new() var ref = ExampleRef.new()
prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id()) prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test")) prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
prints("vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
$Example.varargs_func_void("some", "arguments", "to", "test")
prints("test array", $Example.test_array()) prints("test array", $Example.test_array())
prints("test dictionary", $Example.test_dictionary()) prints("test dictionary", $Example.test_dictionary())

View File

@ -65,6 +65,20 @@ void Example::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func", &Example::varargs_func, mi); ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func", &Example::varargs_func, mi);
} }
{
MethodInfo mi;
mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
mi.name = "varargs_func_nv";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func_nv", &Example::varargs_func_nv, mi);
}
{
MethodInfo mi;
mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
mi.name = "varargs_func_void";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func_void", &Example::varargs_func_void, mi);
}
// Properties. // Properties.
ADD_GROUP("Test group", "group_"); ADD_GROUP("Test group", "group_");
ADD_SUBGROUP("Test subgroup", "group_subgroup_"); ADD_SUBGROUP("Test subgroup", "group_subgroup_");
@ -129,10 +143,19 @@ Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
} }
Variant Example::varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) { Variant Example::varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs called with ", String::num((double)arg_count), " arguments"); UtilityFunctions::print("Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
return arg_count; return arg_count;
} }
int Example::varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs (int return) called with ", String::num((double)arg_count), " arguments");
return 42;
}
void Example::varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs (no return) called with ", String::num((double)arg_count), " arguments");
}
void Example::emit_custom_signal(const String &name, int value) { void Example::emit_custom_signal(const String &name, int value) {
emit_signal("custom_signal", name, value); emit_signal("custom_signal", name, value);
} }

View File

@ -87,6 +87,8 @@ public:
ExampleRef *return_extended_ref() const; ExampleRef *return_extended_ref() const;
Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const; Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const;
Variant varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error); Variant varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
int varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
void varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
void emit_custom_signal(const String &name, int value); void emit_custom_signal(const String &name, int value);
Array test_array() const; Array test_array() const;