diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am index d086bff103..77a62e3639 100644 --- a/src/Makefile_Eolian_Cxx.am +++ b/src/Makefile_Eolian_Cxx.am @@ -70,33 +70,39 @@ tests/eolian_cxx/a.c \ tests/eolian_cxx/b.c \ tests/eolian_cxx/c.c \ tests/eolian_cxx/d.c \ +tests/eolian_cxx/eolian_cxx_test_binding.cc \ tests/eolian_cxx/eolian_cxx_test_callback.cc \ tests/eolian_cxx/eolian_cxx_test_address_of.cc \ tests/eolian_cxx/eolian_cxx_test_wrapper.cc \ tests/eolian_cxx/simple.c \ +tests/eolian_cxx/generic.c \ tests/eolian_cxx/eolian_cxx_test_inheritance.cc \ tests/eolian_cxx/eolian_cxx_test_generate.cc tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_wrapper.$(OBJEXT): tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_callback.$(OBJEXT): tests/eolian_cxx/callback.eo.hh +tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_inheritance.$(OBJEXT): tests/eolian_cxx/simple.eo.hh +tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_binding.$(OBJEXT): tests/eolian_cxx/generic.eo.hh tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_address_of.$(OBJEXT): tests/eolian_cxx/a.eo.hh tests/eolian_cxx/b.eo.hh tests/eolian_cxx/c.eo.hh tests/eolian_cxx/d.eo.hh tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-callback.$(OBJEXT): tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h +tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-simple.$(OBJEXT): tests/eolian_cxx/simple.eo.c tests/eolian_cxx/simple.eo.h +tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-generic.$(OBJEXT): tests/eolian_cxx/generic.eo.c tests/eolian_cxx/generic.eo.h tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-a.$(OBJEXT): tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-b.$(OBJEXT): tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-c.$(OBJEXT): tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-d.$(OBJEXT): tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h -tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_inheritance.$(OBJEXT): tests/eolian_cxx/simple.eo.hh - -tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-simple.$(OBJEXT): tests/eolian_cxx/simple.eo.c tests/eolian_cxx/simple.eo.h - CLEANFILES += tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.c \ tests/eolian_cxx/callback.eo.h \ tests/eolian_cxx/simple.eo.c \ tests/eolian_cxx/simple.eo.h \ tests/eolian_cxx/simple.eo.hh \ tests/eolian_cxx/simple.eo.impl.hh \ +tests/eolian_cxx/generic.eo.c \ +tests/eolian_cxx/generic.eo.h \ +tests/eolian_cxx/generic.eo.hh \ +tests/eolian_cxx/generic.eo.impl.hh \ tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.impl.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \ tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.impl.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \ tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.impl.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \ @@ -125,6 +131,7 @@ endif EXTRA_DIST += tests/eolian_cxx/callback.eo \ tests/eolian_cxx/simple.eo \ +tests/eolian_cxx/generic.eo \ tests/eolian_cxx/a.eo \ tests/eolian_cxx/b.eo \ tests/eolian_cxx/c.eo \ diff --git a/src/Makefile_Eolian_Cxx_Helper.am b/src/Makefile_Eolian_Cxx_Helper.am index bb656c8f28..b754edf635 100644 --- a/src/Makefile_Eolian_Cxx_Helper.am +++ b/src/Makefile_Eolian_Cxx_Helper.am @@ -12,10 +12,7 @@ am__v_EOLCXX_0 = @echo " EOLCXX " $@; SUFFIXES += .eo.hh -%.eo.hh: %.eo $(_EOLIAN_CXX_DEP) +%.eo.impl.hh %.eo.hh: %.eo $(_EOLIAN_CXX_DEP) $(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -o $@ $< -%.eo.impl.hh: %.eo.hh $(_EOLIAN_CXX_DEP) - true $< - CLEANFILES += $(BUILT_SOURCES) diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc index 22ee22f0e5..4d03c8f775 100644 --- a/src/bin/eolian_cxx/convert.cc +++ b/src/bin/eolian_cxx/convert.cc @@ -212,6 +212,20 @@ _convert_property_get_to_function(Eolian_Class const& klass, return get_; } +static efl::eolian::eo_function +_convert_function(Eolian_Class const& klass, Eolian_Function const& func) +{ + return { + function_type(func), + function_scope(func), + function_name(func), + function_impl(func), + function_return_type(func), + _convert_eolian_parameters(func), + convert_comments_function(klass, func, eolian_cxx::method) + }; +} + void convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass) @@ -276,32 +290,42 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass) , last; first != last; ++first) { Eolian_Function const& func = *first; - Eolian_Function_Type const func_type = function_op_type(func); - if (!function_is_visible(func, func_type)) - continue; - - if (function_is_constructor(klass, func)) + if (function_is_visible(func, function_op_type(func)) && + !function_is_constructor(klass, func)) { - cls.constructors.push_back({ - function_impl(func), - _convert_eolian_parameters(func), - convert_comments_function(klass, func) - }); - } - else - { - cls.functions.push_back({ - function_type(func), - function_scope(func), - function_name(func), - function_impl(func), - function_return_type(func), - _convert_eolian_parameters(func), - convert_comments_function(klass, func, eolian_cxx::method) - }); + cls.functions.push_back(_convert_function(klass, func)); } } + if (class_eo_name(klass) != "EO_BASE_CLASS") + for(efl::eina::iterator first ( ::eolian_class_constructors_get(&klass)) + , last; first != last; ++first) + { + Eolian_Constructor const& ctor = *first; + Eolian_Function const& func = *(::eolian_constructor_function_get(&ctor)); + + efl::eolian::eo_function f; + if (::eolian_function_type_get(&func) != EOLIAN_PROPERTY) + f = _convert_function(klass, func); + else + f = _convert_property_set_to_function(klass, func); + + + (::eolian_constructor_is_optional(&ctor) ? + cls.optional_constructors : + cls.constructors + ).push_back({ + function_name(func), + f.impl, + f.params, + f.comment + }); + } + + cls.all_constructors = cls.constructors; + cls.all_constructors.insert(cls.all_constructors.end(), + cls.optional_constructors.begin(), cls.optional_constructors.end()); + for(efl::eina::iterator first ( ::eolian_class_functions_get(&klass, EOLIAN_PROPERTY)) , last; first != last; ++first) { diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh index 5cad7976c0..5b6579ed34 100644 --- a/src/bin/eolian_cxx/eolian_wrappers.hh +++ b/src/bin/eolian_cxx/eolian_wrappers.hh @@ -375,10 +375,8 @@ parameter_type(Eolian_Function_Parameter const& parameter, if (!type.front().binding.empty()) type.front().binding.insert(0, "const "); } - if (::eolian_parameter_is_nonull(¶meter)) - { - type.is_nonull = true; - } + type.is_optional = ::eolian_parameter_is_optional(¶meter) || + ::eolian_parameter_is_nullable(¶meter); return type; } diff --git a/src/bindings/eo_cxx/eo_cxx_interop.hh b/src/bindings/eo_cxx/eo_cxx_interop.hh index 08ca3005ba..ef3e9c73f5 100644 --- a/src/bindings/eo_cxx/eo_cxx_interop.hh +++ b/src/bindings/eo_cxx/eo_cxx_interop.hh @@ -6,10 +6,13 @@ #include #include #include +#include #include #include +#include "eo_concrete.hh" + namespace efl { namespace eolian { //// From C++ to C @@ -443,6 +446,14 @@ Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED return EO_CALLBACK_CONTINUE; } +template +inline +void register_ev_del_free_callback(Eo* eoptr, Fs&&... fs) +{ + std::initializer_list const v {(fs.register_ev_del_free_callback(eoptr), 0)...}; + (void) v; (void) eoptr; +} + template inline std::vector& get_static_callback_vector() @@ -459,6 +470,16 @@ F* alloc_static_callback(F&& f) return &(get_static_callback_vector().back()); } +/// Miscellaneous + +template +inline +void call_ctors(Fs&&... fs) +{ + std::initializer_list const v {(fs(), 0)...}; + (void) v; +} + } } // namespace efl { namespace eolian { #endif // EFL_EOLIAN_INTEROP_HH diff --git a/src/bindings/eo_cxx/eo_inherit.hh b/src/bindings/eo_cxx/eo_inherit.hh index 734b6b6561..3138d1e9a9 100644 --- a/src/bindings/eo_cxx/eo_inherit.hh +++ b/src/bindings/eo_cxx/eo_inherit.hh @@ -13,16 +13,17 @@ #include "eo_ops.hh" #include "eo_private.hh" +#include "eo_cxx_interop.hh" namespace efl { namespace eo { namespace detail { -template +template Eo_Class const* create_class(eina::index_sequence); -template -void inherit_constructor(void* this_, Args args); +inline +void inherit_constructor(void* this_); } @@ -67,23 +68,26 @@ struct inherit /// typedef inherit inherit_base; + //@{ /// @brief Class constructor. /// /// @ref inherit has a "variadic" constructor implementation that /// allows from zero to EFL_MAX_ARGS heterogeneous parameters. /// template - inherit(Args&& ... args) + inherit(efl::eo::parent_type _p, Args&& ... args) { - typedef std::tuple::type...> tuple_type; - _eo_cls = detail::create_class (eina::make_index_sequence()); - _eo_raw = eo_add_ref - (_eo_cls, NULL, - detail::inherit_constructor - - (static_cast(this), tuple_type(std::forward(args)...))); + _eo_cls = detail::create_class (eina::make_index_sequence()); + _eo_raw = eo_add_ref(_eo_cls, _p._eo_raw, detail::inherit_constructor(this), ::efl::eolian::call_ctors(args...)); + ::efl::eolian::register_ev_del_free_callback(_eo_raw, args...); } + template + inherit(Args&& ... args) + : inherit(::efl::eo::parent = nullptr, std::forward(args)...) + {} + //@} + /// @brief Class destructor. /// ~inherit() diff --git a/src/bindings/eo_cxx/eo_inherit_bindings.hh b/src/bindings/eo_cxx/eo_inherit_bindings.hh index 73fc2b1554..6022c1d305 100644 --- a/src/bindings/eo_cxx/eo_inherit_bindings.hh +++ b/src/bindings/eo_cxx/eo_inherit_bindings.hh @@ -10,46 +10,6 @@ namespace efl { namespace eo { namespace detail { /// @addtogroup Efl_Cxx_Detail /// @{ -/// @internal -/// -/// @brief Invokes the EO C Constructor that corresponds to the -/// binded EO C++ Class. -/// -/// @param T The corresponding EO C++ Class -/// @param Args An heterogeneous list of constructor arguments -/// -/// @param tag Used to instruct the compiler during compile-time which -/// of the overloads should be invoked. -/// @param eo A pointer to the EO C Object to be constructed. -/// @param cls Unused. -/// @param args An heterogenous vector containing the constructor -/// arguments, in the correct order. -/// -/// To ensure full reciprocity of the C++ binding there must exist one -/// (and only one) implementation of @ref efl::eo::detail::call_constructor -/// for each available EO C++ Class --- the implementations -/// are differentiated by this unique specialization of -/// @ref efl::eo::detail::tag for the first argument of -/// @ref efl::eo::detail::call_constructor. -/// -/// For example this is how the overload for @ref eo_simple is -/// written as follows: -/// -/// @dontinclude eo_simple.hh -/// @skip call_constructor -/// @until } -/// -/// As you can see @c ::simple_constructor is called with a single -/// argument in this case. Each EO Class has its own constructor -/// prototype -- which can have different argument types as well as -/// distinct number of arguments, etc. -- hence the need to specify a -/// choice for every known EO C++ Class. -/// -/// @see efl::eo::detail::tag -/// -template -void call_constructor(efl::eo::detail::tag tag, Eo* eo, Eo_Class const* cls, Args args); - /// @internal /// /// @brief Sums up the number of EO Operations of each class @@ -73,132 +33,6 @@ struct operation_description_size<> static const int value = 0; }; -template -struct is_args_class : std::false_type -{ -}; - -template -struct is_args_class > - : std::true_type -{ -}; - -template -struct are_args_class; - -template <> -struct are_args_class > - : std::true_type -{ -}; - -template -struct are_args_class > - : std::integral_constant - ::value - && are_args_class >::value - > -{ -}; - -template -struct has_args_class : std::false_type -{ - typedef std::integral_constant index; -}; - -template -struct has_args_class, Args...> > - : std::true_type -{ - typedef detail::args_class type; - typedef std::integral_constant index; -}; - -template -struct has_args_class > - : has_args_class > -{ - typedef has_args_class > base_type; - typedef std::integral_constant - index; -}; - -/// @internal -/// -/// @brief An auxiliary template-class used to select the correct -/// implementation of @ref efl::eo::call_constructor for @p T with -/// proper parameters and variadic size. -/// -/// @param T An EO C++ Class. -/// -template -struct call_constructor_aux -{ - template - static void do_(Args const&, Eo* eo, Eo_Class const* cls - , P, typename std::enable_if::type* = 0) - { - call_constructor(tag(), eo, cls, args_class >(std::tuple<>())); - } - - template - static void do_(Args const& args, Eo* eo, Eo_Class const* cls - , P, typename std::enable_if::type* = 0) - { - call_constructor(tag(), eo, cls, std::get(args)); - } - - /// @internal - /// - /// @brief Invoke @def efl::eo::detail::call_constructor - /// implementation for the parent and each available extension. - /// - /// @param args An heterogenous sequence of arguments. - /// @param eo The opaque EO Object. - /// @param cls The opaque EO Class. - /// - template - static int do_(Args const& args, Eo* eo, Eo_Class const* cls) - { - static_assert(std::tuple_size::value <= N, ""); - static_assert(are_args_class::value, ""); - do_(args, eo, cls, has_args_class()); - return 0; - } -}; - -template -struct call_constructor_aux -{ - template - static void do_(Args const& args, Eo* eo, Eo_Class const* cls - , std::true_type) - { - static_assert(std::tuple_size::value == 1, ""); - static_assert(std::is_same - ::type::class_type - , T>::value, ""); - call_constructor(tag(), eo, cls, std::get<0u>(args)); - } - - template - static void do_(Args const& args, Eo* eo, Eo_Class const* cls - , std::false_type) - { - call_constructor(tag(), eo, cls, args_class(args)); - } - - template - static int do_(Args const& args, Eo* eo, Eo_Class const* cls) - { - do_(args, eo, cls, has_args_class()); - return 0; - } -}; - template void call_varargs(Args...) { @@ -209,18 +43,14 @@ void call_varargs(Args...) /// @brief The procedure that actually is invoked when the constructor /// of @c D is sought from the EO Subsystem. /// -/// @param obj The opaque EO Object. /// @param self A pointer to @p obj's private data. /// @param this_ A void pointer to the opaque EO Class --- /// passed as user data. -/// @param args The arguments for the underlying constructor. /// -template -void inherit_constructor_impl(Eo* obj, Inherit_Private_Data* self, void* this_, Args args) +inline +void inherit_constructor_impl(Eo*, Inherit_Private_Data* self, void* this_) { self->this_ = this_; - Eo_Class const* cls = static_cast*>(this_)->_eo_class(); - detail::call_varargs(detail::call_constructor_aux::do_(args, obj, cls) ...); } /// @internal @@ -231,16 +61,16 @@ void inherit_constructor_impl(Eo* obj, Inherit_Private_Data* self, void* this_, /// @param this_ The user data to be passed to the resolved function. /// @param args An heterogeneous sequence of arguments. /// -template -EAPI void inherit_constructor(void* this_, Args args) +EAPI inline +void inherit_constructor(void* this_) { - typedef void (*func_t)(Eo *, void *, void*, Args); + typedef void (*func_t)(Eo *, void *, void*); Eo_Op_Call_Data ___call; static Eo_Op op = EO_NOOP; if ( op == EO_NOOP ) op = _eo_api_op_id_get (reinterpret_cast - (static_cast(&detail::inherit_constructor)), + (&detail::inherit_constructor), ::eina_main_loop_is(), __FILE__, __LINE__); if (!_eo_call_resolve("detail::inherit_constructor", op, &___call, ::eina_main_loop_is(), __FILE__, __LINE__)) @@ -251,7 +81,7 @@ EAPI void inherit_constructor(void* this_, Args args) } func_t func = (func_t) ___call.func; EO_HOOK_CALL_PREPARE(eo_hook_call_pre, ""); - func(___call.obj, ___call.data, this_, args); + func(___call.obj, ___call.data, this_); EO_HOOK_CALL_PREPARE(eo_hook_call_post, ""); } @@ -289,7 +119,7 @@ operation_description_index<0u, E...> /// /// @see efl::eo::inherit::inherit /// -template +template Eo_Class const* create_class(eina::index_sequence) { static const Eo_Class* my_class = NULL; @@ -299,14 +129,12 @@ Eo_Class const* create_class(eina::index_sequence) op_descs[detail::operation_description_size::value].func = reinterpret_cast ( - static_cast - (&detail::inherit_constructor_impl) + &detail::inherit_constructor_impl ); op_descs[detail::operation_description_size::value].api_func = reinterpret_cast ( - static_cast - (&detail::inherit_constructor) + &detail::inherit_constructor ); op_descs[detail::operation_description_size::value].op = EO_NOOP; op_descs[detail::operation_description_size::value].op_type = EO_OP_TYPE_REGULAR; diff --git a/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc b/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc index 8c41c0eab7..c9334bc5df 100644 --- a/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc +++ b/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc @@ -28,7 +28,7 @@ example_callbacks() { int count = 0; efl::ecore::poller poller( - poller.ecore_poller_constructor(ECORE_POLLER_CORE, 1, + poller.constructor(ECORE_POLLER_CORE, 1, [&count, &poller] { if (++count == 5) diff --git a/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc b/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc index 0e6fce92f0..bdfa3ad19f 100644 --- a/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc +++ b/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc @@ -17,7 +17,7 @@ struct ColourableCircle : efl::eo::inherit { ColourableCircle(int rgb) - : inherit_base(efl::eo::args<::colourable>(rgb)) + : inherit_base(::colourable::rgb_24bits_constructor(rgb)) {} int colour_get() @@ -46,7 +46,7 @@ struct ColourableBar : efl::eo::inherit { ColourableBar() - : inherit_base(efl::eo::args<::colourablesquare>(0)) + : inherit_base(::colourable::rgb_24bits_constructor(0)) {} int colour_get() diff --git a/src/examples/eolian_cxx/eolian_cxx_simple_01.cc b/src/examples/eolian_cxx/eolian_cxx_simple_01.cc index 47b98cb4ce..04acebb138 100644 --- a/src/examples/eolian_cxx/eolian_cxx_simple_01.cc +++ b/src/examples/eolian_cxx/eolian_cxx_simple_01.cc @@ -19,13 +19,13 @@ main() int r, g, b; ::colourable obj1( - obj1.colourable_rgb_24bits_constructor(0x123456) + obj1.rgb_24bits_constructor(0x123456) ); obj1.colour_set(0xc0ffee); obj1.composite_colour_get(&r, &g, &b); ::colourablesquare obj2( - obj2.colourablesquare_size_constructor(10) + obj2.size_constructor(10) ); obj2.composite_colour_set(r, g, b); obj2.size_set(11); diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh index b50e692ac1..987be69740 100644 --- a/src/lib/eolian_cxx/eo_types.hh +++ b/src/lib/eolian_cxx/eo_types.hh @@ -90,21 +90,21 @@ struct eolian_type_instance { eolian_type_instance() : is_out(false) - , is_nonull(false) + , is_optional(false) , parts() {} eolian_type_instance(std::initializer_list il, bool is_out_ = false, - bool is_nonull_ = false) + bool is_optional_ = false) : is_out(is_out_) - , is_nonull(is_nonull_) + , is_optional(is_optional_) , parts(il) {} explicit eolian_type_instance(std::size_t size) : is_out(false) - , is_nonull(false) + , is_optional(false) , parts(size) {} @@ -115,7 +115,7 @@ struct eolian_type_instance eolian_type const& front() const { return parts.front(); } bool is_out; - bool is_nonull; + bool is_optional; eolian_type_container parts; }; @@ -174,9 +174,9 @@ type_binding_requires_optional(eolian_type_instance const& type) } inline bool -type_is_nonull(eolian_type_instance const& type) +type_is_optional(eolian_type_instance const& type) { - return type.is_nonull; + return type.is_optional; } inline eolian_type @@ -254,6 +254,8 @@ struct eo_class ancestors_container_type parents; ancestors_container_type ancestors; constructors_container_type constructors; + constructors_container_type optional_constructors; + constructors_container_type all_constructors; functions_container_type functions; events_container_type own_events; events_container_type concrete_events; @@ -270,6 +272,7 @@ struct eo_parameter struct eo_constructor { std::string name; + std::string impl; parameters_container_type params; std::string comment; }; diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh index 268855284d..5389a5d92d 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh @@ -109,8 +109,8 @@ inline std::ostream& operator<<(std::ostream& out, functors_constructor_methods const& x) { constructors_container_type::const_iterator it, - first = x._cls.constructors.cbegin(), - last = x._cls.constructors.cend(); + first = x._cls.all_constructors.cbegin(), + last = x._cls.all_constructors.cend(); for (it = first; it != last; ++it) { eo_constructor const& c = *it; @@ -136,7 +136,7 @@ operator<<(std::ostream& out, functors_constructor_methods const& x) << endl; // Struct constructor - out << tab(2) << constructor_functor_type_name(c) << "(" + out << tab(2) << "explicit " << constructor_functor_type_name(c) << "(" << parameters_declaration(c.params) << ")" << parameters_cxx_generic(c.params, [](param_data d) @@ -160,7 +160,24 @@ operator<<(std::ostream& out, functors_constructor_methods const& x) // Struct operator() out << tab(2) << "void operator()()" << endl << tab(2) << "{" << endl - << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl + << tab(3) << "::" << c.impl << "(" << parameters_forward_to_c(c.params) << ");" << endl + << tab(2) << "}" << endl; + + // Register event to free allocated callbacks when the Eo* is deleted + out << tab(2) << "void register_ev_del_free_callback(Eo* _eoptr)" << endl + << tab(2) << "{" << endl + << tab(3) << "(void) _eoptr;" << endl + << parameters_cxx_generic(c.params, + [](param_data d) + { + if (d.is_cb) + d.out << tab(3) + << "eo_do(_eoptr," << endl + << tab(4) << "eo_event_callback_add(EO_EV_DEL, " + << "&::efl::eolian::free_callback_calback<" + << parameter_no_ref_type(d.type, d.name) + << ">, " << callback_tmp(d.name) << "));" << endl; + }) << tab(2) << "}" << endl; // Struct member variables @@ -198,8 +215,8 @@ inline std::ostream& operator<<(std::ostream& out, constructor_method_function_declarations const& x) { constructors_container_type::const_iterator it, - first = x._cls.constructors.cbegin(), - last = x._cls.constructors.cend(); + first = x._cls.all_constructors.cbegin(), + last = x._cls.all_constructors.cend(); for (it = first; it != last; ++it) { eo_constructor const& c = *it; @@ -216,8 +233,9 @@ operator<<(std::ostream& out, constructor_method_function_declarations const& x) out << comment(c.comment, 1) << template_parameters_declaration(c.params, 1) - << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "(" - << parameters_declaration(c.params) << ") const;" << endl << endl; + << tab(1) << "static " << constructor_functor_type_decl(c) + << " " << c.name << "(" + << parameters_declaration(c.params) << ");" << endl << endl; } return out; @@ -233,8 +251,8 @@ inline std::ostream& operator<<(std::ostream& out, constructor_method_function_definitions const& x) { constructors_container_type::const_iterator it, - first = x._cls.constructors.cbegin(), - last = x._cls.constructors.cend(); + first = x._cls.all_constructors.cbegin(), + last = x._cls.all_constructors.cend(); for (it = first; it != last; ++it) { eo_constructor const& c = *it; @@ -249,7 +267,7 @@ operator<<(std::ostream& out, constructor_method_function_definitions const& x) << "inline " << full_name(x._cls) << "::" << constructor_functor_type_decl(c) << " " << full_name(x._cls, false) << "::" << c.name << "(" - << parameters_declaration(c.params) << ") const" << endl + << parameters_declaration(c.params) << ")" << endl << "{" << endl << tab(1) << "return " << constructor_functor_type_decl(c) << "(" << parameters_forward(c.params) << ");" << endl @@ -280,24 +298,33 @@ operator<<(std::ostream& out, comment_constructor_with_constructor_methods const if (x._cls.constructors.size()) { bool singular = (x._cls.constructors.size() == 1); - out << tab(2) << "Since this class have " << (singular ? "a " : "") << "constructor method" << (singular ? "" : "s") + out << tab(2) << "Since this class have " << (singular ? "a " : "") + << "necessary constructor method" << (singular ? "" : "s") << ", you must call " << (singular ? "it" : "each one of them") << endl << tab(2) << "in the right place within this constructor parameters." << endl << endl; } + if (!x._cls.optional_constructors.empty()) + { + out << tab(2) << "Optional constructors may be called in any combination as the" << endl + << tab(2) << "last parameters." << endl + << endl; + } + out << tab(2) << "Example:" << endl << tab(2) << "@code" << endl - << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(" << endl; + << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(efl::eo::parent = parent_object"; - for (eo_constructor const& c : x._cls.constructors) - out << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")," << endl; + for (eo_constructor const& c : x._cls.all_constructors) + out << "," << endl + << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")"; - out << tab(3) << "efl::eo::parent = parent_object);" << endl + out << ");" << endl << tab(2) << "@endcode" << endl << endl; - for (eo_constructor const& c : x._cls.constructors) + for (eo_constructor const& c : x._cls.all_constructors) out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl; out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl; @@ -307,8 +334,10 @@ operator<<(std::ostream& out, comment_constructor_with_constructor_methods const struct constructor_with_constructor_methods { eo_class const& _cls; - constructor_with_constructor_methods(eo_class const& cls) + bool _with_parent; + constructor_with_constructor_methods(eo_class const& cls, bool with_parent) : _cls(cls) + , _with_parent(with_parent) {} }; @@ -325,9 +354,7 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x) cb_count += parameters_count_callbacks((*it).params); } - out << comment_constructor_with_constructor_methods(x._cls); - - if (cb_count != 0) + if (cb_count != 0 || !x._cls.optional_constructors.empty()) { out << tab(1) << "template <"; for (unsigned i = 0; i != cb_count; ++i) @@ -336,14 +363,26 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x) out << ", "; out << "typename F" << i; } + if (!x._cls.optional_constructors.empty()) + { + if (cb_count != 0) + out << ", "; + out << "typename... FOpts"; + } out << ">" << endl; } - out << tab(1) << x._cls.name << "("; + out << tab(1) << "explicit " << x._cls.name << "("; + + if (x._with_parent) + out << "::efl::eo::parent_type _p"; + { unsigned cb_idx = 0; for (it = first; it != last; ++it) { + if (x._with_parent || it != first) + out << ", "; out << constructor_functor_type_name(*it); if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0) @@ -357,22 +396,54 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x) }) << ">"; } - out << " _c" << (it-first) << ", "; + out << " _c" << (it-first); } assert(cb_idx == cb_count); } - out << "::efl::eo::parent_type _p = (::efl::eo::parent = nullptr))" << endl - << tab(2) << ": " << x._cls.name << "(_ctors_call("; + + if (!x._cls.optional_constructors.empty()) + { + if (x._with_parent || first != last) + out << ", "; + out << "FOpts&&... _opts"; + } + + out << ")" << endl + << tab(2) << ": " << x._cls.name << "(_ctors_call(" + << (x._with_parent ? "_p" : "::efl::eo::parent = nullptr"); for (it = first; it != last; ++it) { - out << "_c" << (it-first) << ", "; + out << ", _c" << (it-first); } - out << "_p))" << endl - << tab(1) << "{}" << endl << endl; + if (!x._cls.optional_constructors.empty()) + { + out << ", std::forward(_opts)..."; + } + out << "))" << endl + << tab(1) << "{}" << endl; return out; } +struct constructors_with_constructor_methods +{ + eo_class const& _cls; + constructors_with_constructor_methods(eo_class const& cls) + : _cls(cls) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, constructors_with_constructor_methods const& x) +{ + out << tab(1) << "//@{" << endl + << comment_constructor_with_constructor_methods(x._cls) + << constructor_with_constructor_methods(x._cls, true) << endl + << constructor_with_constructor_methods(x._cls, false) + << tab(1) << "//@}" << endl << endl; + return out; +} + struct constructor_eo { eo_class const& _cls; @@ -460,24 +531,31 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x) last = x._cls.constructors.cend(); for (it = first; it != last; ++it) { - unsigned param_cb_count = parameters_count_callbacks((*it).params); - for (unsigned i = 0; i != param_cb_count; ++i) - { - if(cb_count == 0) - out << tab(1) << "template <"; - else - out << ", "; - out << "typename F" << cb_count++; - } + cb_count += parameters_count_callbacks((*it).params); + } + if (cb_count != 0 || !x._cls.optional_constructors.empty()) + { + out << tab(1) << "template <"; + for (unsigned i = 0; i != cb_count; ++i) + { + if (i != 0) + out << ", "; + out << "typename F" << i; + } + if (!x._cls.optional_constructors.empty()) + { + if (cb_count != 0) + out << ", "; + out << "typename... FOpts"; + } + out << ">" << endl; } - if (cb_count != 0) - out << ">" << endl; unsigned cb_idx = 0; - out << tab(1) << "static Eo* _ctors_call("; + out << tab(1) << "static Eo* _ctors_call(::efl::eo::parent_type _p"; for (it = first; it != last; ++it) { - out << constructor_functor_type_name(*it); + out << ", " << constructor_functor_type_name(*it); if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0) { @@ -490,39 +568,29 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x) }) << ">"; } - out << " _c" << (it-first) << ", "; + out << " _c" << (it-first); } assert(cb_idx == cb_count); - out << "::efl::eo::parent_type _p)" << endl + if (!x._cls.optional_constructors.empty()) + out << ", FOpts&&... _opts"; + + out << ")" << endl << tab(1) << "{" << endl << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw"; for (it = first; it != last; ++it) { out << ", _c" << (it-first) << "()"; } + if (!x._cls.optional_constructors.empty()) + out << ", ::efl::eolian::call_ctors(_opts...)"; out << ");" << endl << endl; - cb_idx = 0; for (it = first; it != last; ++it) - { - if (parameters_count_callbacks((*it).params) == 0) - continue; + out << tab(2) << "_c" << (it-first) << ".register_ev_del_free_callback(_ret_eo);" << endl; - out << parameters_cxx_generic((*it).params, - [&it, &first, &cb_idx](param_data d) - { - if (d.is_cb) - d.out << tab(2) - << "eo_do(_ret_eo," << endl - << tab(3) << "eo_event_callback_add(EO_EV_DEL, " - << "&::efl::eolian::free_callback_calback, _c" << (it-first) << "." << callback_tmp(d.name) - << "));" << endl; - }) - << endl; - } - assert(cb_idx == cb_count); + if (!x._cls.optional_constructors.empty()) + out << tab(2) << "::efl::eolian::register_ev_del_free_callback(_ret_eo, _opts...);" << endl; out << tab(2) << "return _ret_eo;" << endl << tab(1) << "}" << endl << endl; diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh index c1d227cbcc..e1545fc875 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh @@ -230,7 +230,7 @@ eo_class_declarations_generator(std::ostream& out, eo_class const& cls) << class_inheritance(cls) << '{' << endl << functors_constructor_methods(cls) - << constructor_with_constructor_methods(cls) + << constructors_with_constructor_methods(cls) << constructor_eo(cls) << copy_constructor(cls) << destructor(cls) diff --git a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh index 11b8f2a29e..e134729aa4 100644 --- a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh +++ b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh @@ -315,73 +315,6 @@ operator<<(std::ostream& out, inheritance_base_operations const& x) return out; } -struct inheritance_call_constructor_arguments -{ - parameters_container_type const& _params; - inheritance_call_constructor_arguments(parameters_container_type const& params) - : _params(params) - {} -}; - -inline std::ostream& -operator<<(std::ostream& out, inheritance_call_constructor_arguments const& x) -{ - parameters_container_type::size_type i, n = x._params.size(); - for (i=0; i())"; - } - return out; -} - -struct inheritance_call_constructors -{ - eo_class const& _cls; - inheritance_call_constructors(eo_class const& cls) : _cls(cls) {} -}; - -inline std::ostream& -operator<<(std::ostream& out, inheritance_call_constructors const& x) -{ - constructors_container_type::const_iterator it, - first = x._cls.constructors.begin(), - last = x._cls.constructors.end(); - for (it = first; it != last; ++it) - { - eo_constructor const& ctor = *it; - out << "inline void" << endl - << "call_constructor(::efl::eo::detail::tag< " - << full_name(x._cls) << " >" << endl - << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl - << tab(5) << "::efl::eo::detail::args_class<" - << full_name(x._cls) - << ", ::std::tuple<" - << parameters_types(ctor.params) - << "> > const& args)" << endl - << "{" << endl - << tab(1) << "(void)args;" << endl - << tab(1) - << "eo_do_super(eo, cls, ::" << ctor.name - << "(" << inheritance_call_constructor_arguments(ctor.params) - << "));" << endl - << "}" << endl << endl; - } - - out << "inline void" << endl - << "call_constructor(::efl::eo::detail::tag< " - << full_name(x._cls) << " >" << endl - << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl - << tab(5) << "::efl::eo::detail::args_class<" - << full_name(x._cls) - << ", ::std::tuple<::efl::eo::parent_type> > const& args)" << endl - << "{" << endl - << tab(1) << "eo_do(eo, ::eo_parent_set(args.get<0>()._eo_raw));" << endl - << "}" << endl << endl; - - return out; -} - struct inheritance_eo_class_getter { eo_class const& _cls; @@ -410,7 +343,6 @@ eo_inheritance_detail_generator(std::ostream& out, eo_class const& cls) << inheritance_base_operations(cls) << endl << inheritance_base_operations_size_scopes(cls) << inheritance_operations_description(cls) - << inheritance_call_constructors(cls) << inheritance_eo_class_getter(cls) << "} } }" << endl; } diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh index 193d2ea88a..de01890c98 100644 --- a/src/lib/eolian_cxx/grammar/type_generator.hh +++ b/src/lib/eolian_cxx/grammar/type_generator.hh @@ -110,7 +110,7 @@ operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x) { if (x._type.is_out) res += "*"; - else if (!x._type.is_nonull && x._type.front().binding_requires_optional) + else if (x._type.is_optional && x._type.front().binding_requires_optional) res = "::efl::eina::optional< " + res + " >"; } diff --git a/src/tests/eolian_cxx/eolian_cxx_suite.cc b/src/tests/eolian_cxx/eolian_cxx_suite.cc index cace098d79..7f8043914b 100644 --- a/src/tests/eolian_cxx/eolian_cxx_suite.cc +++ b/src/tests/eolian_cxx/eolian_cxx_suite.cc @@ -9,6 +9,7 @@ void eolian_cxx_test_generate(TCase* tc); void eolian_cxx_test_callback(TCase* tc); void eolian_cxx_test_address_of(TCase* tc); void eolian_cxx_test_inheritance(TCase* tc); +void eolian_cxx_test_binding(TCase* tc); typedef struct _Eolian_Cxx_Test_Case Eolian_Cxx_Test_Case; struct _Eolian_Cxx_Test_Case @@ -24,6 +25,7 @@ static const Eolian_Cxx_Test_Case etc[] = { { "Eolian-Cxx Callback", eolian_cxx_test_callback }, { "Eolian-Cxx Address_of", eolian_cxx_test_address_of }, { "Eolian-Cxx Inheritance", eolian_cxx_test_inheritance }, + { "Eolian-Cxx Binding", eolian_cxx_test_binding }, { NULL, NULL } }; diff --git a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc index ab3703c087..a6d8ebb310 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc @@ -1,2 +1,60 @@ // test EFL++ generated bindings + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include + +START_TEST(eolian_cxx_test_binding_constructor_only_required) +{ + efl::eo::eo_init i; + + bool called1 = false; + + generic g( + g.required_ctor_a(1), + g.required_ctor_b(std::bind([&called1] { called1 = true; })) + ); + + g.call_req_ctor_b_callback(); + g.call_opt_ctor_b_callback(); + + fail_if(!called1); + fail_if(1 != g.req_ctor_a_value_get()); +} +END_TEST + +START_TEST(eolian_cxx_test_binding_constructor_all_optionals) +{ + efl::eo::eo_init i; + + bool called1 = false; + bool called2 = false; + + generic g( + g.required_ctor_a(2), + g.required_ctor_b(std::bind([&called1] { called1 = true; })), + g.optional_ctor_a(3), + g.optional_ctor_b(std::bind([&called2] { called2 = true; })) + ); + + g.call_req_ctor_b_callback(); + g.call_opt_ctor_b_callback(); + + fail_if(!called1); + fail_if(!called2); + fail_if(2 != g.req_ctor_a_value_get()); + fail_if(3 != g.opt_ctor_a_value_get()); +} +END_TEST + +void +eolian_cxx_test_binding(TCase* tc) +{ + tcase_add_test(tc, eolian_cxx_test_binding_constructor_only_required); + tcase_add_test(tc, eolian_cxx_test_binding_constructor_all_optionals); +} diff --git a/src/tests/eolian_cxx/generic.c b/src/tests/eolian_cxx/generic.c new file mode 100644 index 0000000000..1de4e5b6e1 --- /dev/null +++ b/src/tests/eolian_cxx/generic.c @@ -0,0 +1,77 @@ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "generic.eo.h" + +struct _Generic_Data +{ + int req_ctor_a_val; + Ecore_Cb req_ctor_b_cb; + void *req_ctor_b_data; + int opt_ctor_a_val; + Ecore_Cb opt_ctor_b_cb; + void *opt_ctor_b_data; +}; +typedef struct _Generic_Data Generic_Data; + +#define MY_CLASS GENERIC_CLASS + +static void _generic_eo_base_constructor(Eo *obj, Generic_Data *pd) +{ + pd->req_ctor_a_val = 0; + pd->req_ctor_b_cb = NULL; + pd->req_ctor_b_data = NULL; + pd->opt_ctor_a_val = 0; + pd->opt_ctor_b_cb = NULL; + pd->opt_ctor_b_data = NULL; + eo_do_super(obj, MY_CLASS, eo_constructor()); +} + +static void _generic_required_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int value) +{ + pd->req_ctor_a_val = value; +} + +static void _generic_required_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data) +{ + cb(data); +} + +static void _generic_optional_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int value) +{ + pd->opt_ctor_a_val = value; +} + +static void _generic_optional_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data) +{ + cb(data); +} + +static int _generic_req_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd) +{ + return pd->req_ctor_a_val; +} + +static int _generic_opt_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd) +{ + return pd->opt_ctor_a_val; +} + +static void _generic_call_req_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd) +{ + if (pd->req_ctor_b_cb) + pd->req_ctor_b_cb(pd->req_ctor_b_data); +} + +static void _generic_call_opt_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd) +{ + if (pd->opt_ctor_b_cb) + pd->opt_ctor_b_cb(pd->opt_ctor_b_data); +} + +#include "generic.eo.c" diff --git a/src/tests/eolian_cxx/generic.eo b/src/tests/eolian_cxx/generic.eo new file mode 100644 index 0000000000..af21c02a0e --- /dev/null +++ b/src/tests/eolian_cxx/generic.eo @@ -0,0 +1,58 @@ +class Generic (Eo.Base) +{ + legacy_prefix: null; + data: Generic_Data; + properties { + req_ctor_a_value { + get { + } + values { + int value; + } + } + opt_ctor_a_value { + get { + } + values { + int value; + } + } + } + methods { + required_ctor_a { + params { + @in int value; + } + } + required_ctor_b { + params { + @in Ecore_Cb cb; + @in void* data; + } + } + optional_ctor_a { + params { + @in int value; + } + } + optional_ctor_b { + params { + @in Ecore_Cb cb; + @in void* data; + } + } + call_req_ctor_b_callback { + } + call_opt_ctor_b_callback { + } + } + constructors { + .required_ctor_a; + .required_ctor_b; + .optional_ctor_a @optional; + .optional_ctor_b @optional; + } + implements { + Eo.Base.constructor; + } +}