From ce36f0be936f218d87055cf21b643ab327f07853 Mon Sep 17 00:00:00 2001 From: Vitor Sousa Date: Thu, 26 Mar 2015 11:48:09 -0300 Subject: [PATCH] eolain_cxx: Fix C++ support for new Eolian features Added optional constructor methods for C++ Eolian wrappers. Changed the interface of wrappers' main constructors. If there are optional constructor methods they should be passed as variadic template argument at the end of the constructor. To support variadic template arguments, the optional "parent" parameter is now the first parameter and there is another constructor without the "parent" parameter. Checking for @optinal and @nullable attributes instead of @nonull. Now @nonull is the default, and eina::optional is only used when @optional or @nullable attribute is specified. The names of constructor methods no longer have the class name prefixed. Added unit tests for checking the binding of optional constructors. Added new .eo file to be used in the test. Changed the generated documentation of constructors. Changed the efl::eo::inherit accordingly, to address these new features. Now the constructor methods should be explicit called in the efl::eo::inherit constructor, which will receive them via variadic template arguments. Added another constructor to efl::eo::inherit for passing the parent object. Updated some tests and examples to follow the new interface. Removed some code that is no longer necessary. Also, fix Eolian C++ support for constructing properties. fix assertion when parsing constructing properties. Now if a property is a constructing property eolian_cxx will generate a constructor method that have the property name (without the "_set" suffix). --- src/Makefile_Eolian_Cxx.am | 15 +- src/Makefile_Eolian_Cxx_Helper.am | 5 +- src/bin/eolian_cxx/convert.cc | 68 +++++-- src/bin/eolian_cxx/eolian_wrappers.hh | 6 +- src/bindings/eo_cxx/eo_cxx_interop.hh | 21 ++ src/bindings/eo_cxx/eo_inherit.hh | 26 ++- src/bindings/eo_cxx/eo_inherit_bindings.hh | 192 +----------------- .../eolian_cxx/eolian_cxx_callbacks_01.cc | 2 +- .../eolian_cxx/eolian_cxx_inherit_01.cc | 4 +- .../eolian_cxx/eolian_cxx_simple_01.cc | 4 +- src/lib/eolian_cxx/eo_types.hh | 17 +- .../eo_class_constructors_generator.hh | 190 +++++++++++------ .../eolian_cxx/grammar/eo_class_generator.hh | 2 +- .../grammar/inheritance_base_generator.hh | 68 ------- src/lib/eolian_cxx/grammar/type_generator.hh | 2 +- src/tests/eolian_cxx/eolian_cxx_suite.cc | 2 + .../eolian_cxx/eolian_cxx_test_binding.cc | 58 ++++++ src/tests/eolian_cxx/generic.c | 77 +++++++ src/tests/eolian_cxx/generic.eo | 58 ++++++ 19 files changed, 447 insertions(+), 370 deletions(-) create mode 100644 src/tests/eolian_cxx/generic.c create mode 100644 src/tests/eolian_cxx/generic.eo 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; + } +}