From ee4ac30b40e40c4af7ab63cd4b1d0af985adf3a9 Mon Sep 17 00:00:00 2001 From: Karroffel Date: Sun, 23 Jul 2017 16:13:55 +0200 Subject: [PATCH] template magic --- include/core/Godot.hpp | 430 +++++++---------------------------------- 1 file changed, 71 insertions(+), 359 deletions(-) diff --git a/include/core/Godot.hpp b/include/core/Godot.hpp index 320a4f18..3754be76 100644 --- a/include/core/Godot.hpp +++ b/include/core/Godot.hpp @@ -172,377 +172,89 @@ char *___get_method_class_name(R (T::*p)(args... a) const) } -// wohooo, let the fun begin. -template -struct _WrappedMethod0 { - R (T::*f)(); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - T *obj = (T *) user_data; - _WrappedMethod0 *method = (_WrappedMethod0*) method_data; - Variant *var = (Variant *) &v; - *var = (obj->*(method->f))(); - return v; +// Okay, time for some template magic. +// Many thanks to manpat from the GDL Discord Server. + + +// This is stuff that's available in C++14 I think, but whatever. + +template +struct __Sequence{}; + +template +struct __construct_sequence { + using type = typename __construct_sequence::type; +}; + +template +struct __construct_sequence<0, I...> { + using type = __Sequence; +}; + + +// Now the wrapping part. +template +struct _WrappedMethod { + R (T::*f)(As...); + + template + void apply(Variant* ret, T* obj, Variant** args, __Sequence) { + *ret = (obj->*f)( _ArgCast::_arg_cast(*args[I])... ); + } +}; + +template +struct _WrappedMethod { + void (T::*f)(As...); + + template + void apply(Variant* ret, T* obj, Variant** args, __Sequence) { + (obj->*f)( _ArgCast::_arg_cast(*args[I])... ); } }; -template -struct _WrappedMethod0 { - void (T::*f)(); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod0 *method = (_WrappedMethod0*) method_data; - - (obj->*(method->f))(); - - return v; - } -}; - -template -void *___make_wrapper_function(R (T::*f)()) +template +godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) { - _WrappedMethod0 *p = (_WrappedMethod0 *) malloc(sizeof(_WrappedMethod0)); + godot_variant v; + godot_variant_new_nil(&v); + + T *obj = (T *) user_data; + _WrappedMethod *method = (_WrappedMethod*) method_data; + + Variant *var = (Variant *) &v; + Variant **arg = (Variant **) args; + + method->apply(var, obj, arg, typename __construct_sequence::type {}); + + return v; +} + +template +void *___make_wrapper_function(R (T::*f)(As...)) +{ + using MethodType = _WrappedMethod; + MethodType *p = (MethodType *) godot_alloc(sizeof(MethodType)); p->f = f; return (void *) p; } -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)()) +template +__godot_wrapper_method ___get_wrapper_function(R (T::*f)(As...)) { - return (__godot_wrapper_method) &_WrappedMethod0::__wrapped_method; + return (__godot_wrapper_method) &__wrapped_method; } - - - -template -struct _WrappedMethod1 { - R (T::*f)(A0); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod1 *method = (_WrappedMethod1*) method_data; - - Variant *var = (Variant *) &v; - Variant **arg = (Variant **) args; - - *var = (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0])); - - return v; - } -}; - -template -struct _WrappedMethod1 { - void (T::*f)(A0); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod1 *method = (_WrappedMethod1*) method_data; - - Variant **arg = (Variant **) args; - - (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0])); - - return v; - } -}; - - -template -void *___make_wrapper_function(R (T::*f)(A0)) -{ - _WrappedMethod1 *p = (_WrappedMethod1 *) malloc(sizeof(_WrappedMethod1)); - p->f = f; - return (void *) p; -} - -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A0)) -{ - return (__godot_wrapper_method) &_WrappedMethod1::__wrapped_method; -} - - - - - - - - - - - - -template -struct _WrappedMethod2 { - R (T::*f)(A0, A1); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod2 *method = (_WrappedMethod2*) method_data; - - Variant *var = (Variant *) &v; - Variant **arg = (Variant **) args; - - *var = (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1])); - - return v; - } -}; - -template -struct _WrappedMethod2 { - void (T::*f)(A0, A1); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod2 *method = (_WrappedMethod2*) method_data; - - Variant **arg = (Variant **) args; - - (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1])); - - return v; - } -}; - - -template -void *___make_wrapper_function(R (T::*f)(A0, A1)) -{ - _WrappedMethod2 *p = (_WrappedMethod2 *) malloc(sizeof(_WrappedMethod2)); - p->f = f; - return (void *) p; -} - -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A0, A1)) -{ - return (__godot_wrapper_method) &_WrappedMethod2::__wrapped_method; -} - - - - - - - - - - - - -template -struct _WrappedMethod3 { - R (T::*f)(A0, A1, A2); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod3 *method = (_WrappedMethod3*) method_data; - - Variant *var = (Variant *) &v; - Variant **arg = (Variant **) args; - - *var = (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2])); - - return v; - } -}; - -template -struct _WrappedMethod3 { - void (T::*f)(A0, A1, A2); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod3 *method = (_WrappedMethod3*) method_data; - - Variant **arg = (Variant **) args; - - (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2])); - - return v; - } -}; - - -template -void *___make_wrapper_function(R (T::*f)(A0, A1, A2)) -{ - _WrappedMethod3 *p = (_WrappedMethod3 *) malloc(sizeof(_WrappedMethod3)); - p->f = f; - return (void *) p; -} - -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A0, A1, A2)) -{ - return (__godot_wrapper_method) &_WrappedMethod3::__wrapped_method; -} - - - - - - - - - - - -template -struct _WrappedMethod4 { - R (T::*f)(A0, A1, A2, A3); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod4 *method = (_WrappedMethod4*) method_data; - - Variant *var = (Variant *) &v; - Variant **arg = (Variant **) args; - - *var = (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2]), _ArgCast::_arg_cast(*arg[3])); - - return v; - } -}; - -template -struct _WrappedMethod4 { - void (T::*f)(A0, A1, A2, A3); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod4 *method = (_WrappedMethod4*) method_data; - - Variant **arg = (Variant **) args; - - (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2]), _ArgCast::_arg_cast(*arg[3])); - - return v; - } -}; - - -template -void *___make_wrapper_function(R (T::*f)(A0, A1, A2, A3)) -{ - _WrappedMethod4 *p = (_WrappedMethod4 *) malloc(sizeof(_WrappedMethod4)); - p->f = f; - return (void *) p; -} - -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A0, A1, A2, A3)) -{ - return (__godot_wrapper_method) &_WrappedMethod4::__wrapped_method; -} - - - - - - - - - - -template -struct _WrappedMethod5 { - R (T::*f)(A0, A1, A2, A3, A4); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod5 *method = (_WrappedMethod5*) method_data; - - Variant *var = (Variant *) &v; - Variant **arg = (Variant **) args; - - *var = (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2]), _ArgCast::_arg_cast(*arg[3]), _ArgCast::_arg_cast(*arg[4])); - - return v; - } -}; - -template -struct _WrappedMethod5 { - void (T::*f)(A0, A1, A2, A3, A4); - static godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int num_args, godot_variant **args) - { - godot_variant v; - godot_variant_new_nil(&v); - - T *obj = (T *) user_data; - _WrappedMethod5 *method = (_WrappedMethod5*) method_data; - - Variant **arg = (Variant **) args; - - (obj->*(method->f))(_ArgCast::_arg_cast(*arg[0]), _ArgCast::_arg_cast(*arg[1]), _ArgCast::_arg_cast(*arg[2]), _ArgCast::_arg_cast(*arg[3]), _ArgCast::_arg_cast(*arg[4])); - - return v; - } -}; - - -template -void *___make_wrapper_function(R (T::*f)(A0, A1, A2, A3, A4)) -{ - _WrappedMethod5 *p = (_WrappedMethod5 *) malloc(sizeof(_WrappedMethod5)); - p->f = f; - return (void *) p; -} - -template -__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A0, A1, A2, A3, A4)) -{ - return (__godot_wrapper_method) &_WrappedMethod5::__wrapped_method; -} - template void *___make_wrapper_function(R (T::*f)(A...) const) { @@ -573,7 +285,7 @@ void register_method(char *name, M method_ptr, godot_method_rpc_mode rpc_type = { godot_instance_method method = {}; method.method_data = ___make_wrapper_function(method_ptr); - method.free_func = free; + method.free_func = godot_free; method.method = (__godot_wrapper_method) ___get_wrapper_function(method_ptr); @@ -682,20 +394,20 @@ void register_property(char *name, P (T::*var), P default_value, godot_method_rp attr.usage = usage; attr.hint_string = *_hint_string; - _PropertyDefaultSetFunc *wrapped_set = (_PropertyDefaultSetFunc *) malloc(sizeof(_PropertyDefaultSetFunc)); + _PropertyDefaultSetFunc *wrapped_set = (_PropertyDefaultSetFunc *) godot_alloc(sizeof(_PropertyDefaultSetFunc)); wrapped_set->f = var; - _PropertyDefaultGetFunc *wrapped_get = (_PropertyDefaultGetFunc *) malloc(sizeof(_PropertyDefaultGetFunc)); + _PropertyDefaultGetFunc *wrapped_get = (_PropertyDefaultGetFunc *) godot_alloc(sizeof(_PropertyDefaultGetFunc)); wrapped_get->f = var; godot_property_set_func set_func = {}; set_func.method_data = (void *) wrapped_set; - set_func.free_func = free; + set_func.free_func = godot_free; set_func.set_func = &_PropertyDefaultSetFunc::_wrapped_setter; godot_property_get_func get_func = {}; get_func.method_data = (void *) wrapped_get; - get_func.free_func = free; + get_func.free_func = godot_free; get_func.get_func = &_PropertyDefaultGetFunc::_wrapped_getter; godot_script_register_property(T::___get_type_name(), name, &attr, set_func, get_func); @@ -716,20 +428,20 @@ void register_property(char *name, void (T::*setter)(P), P (T::*getter)(), P def attr.rset_type = rpc_mode; attr.usage = usage; - _PropertySetFunc *wrapped_set = (_PropertySetFunc *) malloc(sizeof(_PropertySetFunc)); + _PropertySetFunc *wrapped_set = (_PropertySetFunc *) godot_alloc(sizeof(_PropertySetFunc)); wrapped_set->f = setter; - _PropertyGetFunc *wrapped_get = (_PropertyGetFunc *) malloc(sizeof(_PropertyGetFunc)); + _PropertyGetFunc *wrapped_get = (_PropertyGetFunc *) godot_alloc(sizeof(_PropertyGetFunc)); wrapped_get->f = getter; godot_property_set_func set_func = {}; set_func.method_data = (void *) wrapped_set; - set_func.free_func = free; + set_func.free_func = godot_free; set_func.set_func = &_PropertySetFunc::_wrapped_setter; godot_property_get_func get_func = {}; get_func.method_data = (void *) wrapped_get; - get_func.free_func = free; + get_func.free_func = godot_free; get_func.get_func = &_PropertyGetFunc::_wrapped_getter; godot_script_register_property(T::___get_type_name(), name, &attr, set_func, get_func);