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).
This commit is contained in:
Vitor Sousa 2015-03-26 11:48:09 -03:00 committed by Felipe Magno de Almeida
parent 72604d4957
commit ce36f0be93
19 changed files with 447 additions and 370 deletions

View File

@ -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 \

View File

@ -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)

View File

@ -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<const Eolian_Constructor> 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<const Eolian_Function> first ( ::eolian_class_functions_get(&klass, EOLIAN_PROPERTY))
, last; first != last; ++first)
{

View File

@ -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(&parameter))
{
type.is_nonull = true;
}
type.is_optional = ::eolian_parameter_is_optional(&parameter) ||
::eolian_parameter_is_nullable(&parameter);
return type;
}

View File

@ -6,10 +6,13 @@
#include <tuple>
#include <utility>
#include <type_traits>
#include <initializer_list>
#include <Eina.hh>
#include <Eo.hh>
#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 <typename... Fs>
inline
void register_ev_del_free_callback(Eo* eoptr, Fs&&... fs)
{
std::initializer_list<int const> const v {(fs.register_ev_del_free_callback(eoptr), 0)...};
(void) v; (void) eoptr;
}
template <typename F>
inline
std::vector<F>& get_static_callback_vector()
@ -459,6 +470,16 @@ F* alloc_static_callback(F&& f)
return &(get_static_callback_vector<F>().back());
}
/// Miscellaneous
template <typename... Fs>
inline
void call_ctors(Fs&&... fs)
{
std::initializer_list<int const> const v {(fs(), 0)...};
(void) v;
}
} } // namespace efl { namespace eolian {
#endif // EFL_EOLIAN_INTEROP_HH

View File

@ -13,16 +13,17 @@
#include "eo_ops.hh"
#include "eo_private.hh"
#include "eo_cxx_interop.hh"
namespace efl { namespace eo {
namespace detail {
template <typename D, typename Args, typename... E, std::size_t... S>
template <typename D, typename... E, std::size_t... S>
Eo_Class const* create_class(eina::index_sequence<S...>);
template <typename Args, typename ... E>
void inherit_constructor(void* this_, Args args);
inline
void inherit_constructor(void* this_);
}
@ -67,23 +68,26 @@ struct inherit
///
typedef inherit<D, E...> inherit_base;
//@{
/// @brief Class constructor.
///
/// @ref inherit has a "variadic" constructor implementation that
/// allows from zero to EFL_MAX_ARGS heterogeneous parameters.
///
template<typename... Args>
inherit(Args&& ... args)
inherit(efl::eo::parent_type _p, Args&& ... args)
{
typedef std::tuple<typename std::remove_reference<Args>::type...> tuple_type;
_eo_cls = detail::create_class<D, tuple_type, E...> (eina::make_index_sequence<sizeof...(E)>());
_eo_raw = eo_add_ref
(_eo_cls, NULL,
detail::inherit_constructor
<tuple_type, E...>
(static_cast<void*>(this), tuple_type(std::forward<Args>(args)...)));
_eo_cls = detail::create_class<D, E...> (eina::make_index_sequence<sizeof...(E)>());
_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<typename... Args>
inherit(Args&& ... args)
: inherit(::efl::eo::parent = nullptr, std::forward<Args>(args)...)
{}
//@}
/// @brief Class destructor.
///
~inherit()

View File

@ -10,46 +10,6 @@ namespace efl { namespace eo { namespace detail {
/// @addtogroup Efl_Cxx_Detail
/// @{
/// @internal
///
/// @brief Invokes the <em>EO C Constructor</em> that corresponds to the
/// binded <em>EO C++ Class</em>.
///
/// @param T The corresponding <em>EO C++ Class</em>
/// @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 <em>EO C Object</em> 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 <em>EO C++ Class</em> --- 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 <em>EO C++ Class</em>.
///
/// @see efl::eo::detail::tag
///
template <typename T, typename Args>
void call_constructor(efl::eo::detail::tag<T> tag, Eo* eo, Eo_Class const* cls, Args args);
/// @internal
///
/// @brief Sums up the number of <em>EO Operations</em> of each class
@ -73,132 +33,6 @@ struct operation_description_size<>
static const int value = 0;
};
template <typename T>
struct is_args_class : std::false_type
{
};
template <typename T, typename Tuple>
struct is_args_class<args_class<T, Tuple> >
: std::true_type
{
};
template <typename Tuple>
struct are_args_class;
template <>
struct are_args_class<std::tuple<> >
: std::true_type
{
};
template <typename T0, typename... T>
struct are_args_class<std::tuple<T0, T...> >
: std::integral_constant
<bool
, is_args_class<T0>::value
&& are_args_class<std::tuple<T...> >::value
>
{
};
template <typename T, typename Tuple>
struct has_args_class : std::false_type
{
typedef std::integral_constant<std::size_t, 0u> index;
};
template <typename T, typename Tuple, typename... Args>
struct has_args_class<T, std::tuple<detail::args_class<T, Tuple>, Args...> >
: std::true_type
{
typedef detail::args_class<T, Tuple> type;
typedef std::integral_constant<std::size_t, 0u> index;
};
template <typename T, typename T0, typename... Args>
struct has_args_class<T, std::tuple<T0, Args...> >
: has_args_class<T, std::tuple<Args...> >
{
typedef has_args_class<T, std::tuple<Args...> > base_type;
typedef std::integral_constant
<std::size_t, 1u + base_type::index::value> 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 <em>EO C++ Class</em>.
///
template <typename T, std::size_t N>
struct call_constructor_aux
{
template <typename Args, typename P>
static void do_(Args const&, Eo* eo, Eo_Class const* cls
, P, typename std::enable_if<!P::value>::type* = 0)
{
call_constructor(tag<T>(), eo, cls, args_class<T, std::tuple<> >(std::tuple<>()));
}
template <typename Args, typename P>
static void do_(Args const& args, Eo* eo, Eo_Class const* cls
, P, typename std::enable_if<P::value>::type* = 0)
{
call_constructor(tag<T>(), eo, cls, std::get<P::index::value>(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 <em>EO Object</em>.
/// @param cls The opaque <em>EO Class</em>.
///
template <typename Args>
static int do_(Args const& args, Eo* eo, Eo_Class const* cls)
{
static_assert(std::tuple_size<Args>::value <= N, "");
static_assert(are_args_class<Args>::value, "");
do_(args, eo, cls, has_args_class<T, Args>());
return 0;
}
};
template <typename T>
struct call_constructor_aux<T, 1u>
{
template <typename Args>
static void do_(Args const& args, Eo* eo, Eo_Class const* cls
, std::true_type)
{
static_assert(std::tuple_size<Args>::value == 1, "");
static_assert(std::is_same
<typename std::tuple_element<0u, Args>::type::class_type
, T>::value, "");
call_constructor(tag<T>(), eo, cls, std::get<0u>(args));
}
template <typename Args>
static void do_(Args const& args, Eo* eo, Eo_Class const* cls
, std::false_type)
{
call_constructor(tag<T>(), eo, cls, args_class<T, Args>(args));
}
template <typename Args>
static int do_(Args const& args, Eo* eo, Eo_Class const* cls)
{
do_(args, eo, cls, has_args_class<T, Args>());
return 0;
}
};
template <typename... Args>
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 <em>EO Subsystem</em>.
///
/// @param obj The opaque <em>EO Object</em>.
/// @param self A pointer to @p obj's private data.
/// @param this_ A void pointer to the opaque <em>EO Class</em> ---
/// passed as <em>user data</em>.
/// @param args The arguments for the underlying constructor.
///
template <typename D, typename Args, typename... E>
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<inherit<D, E...>*>(this_)->_eo_class();
detail::call_varargs(detail::call_constructor_aux<E, sizeof...(E)>::do_(args, obj, cls) ...);
}
/// @internal
@ -231,16 +61,16 @@ void inherit_constructor_impl(Eo* obj, Inherit_Private_Data* self, void* this_,
/// @param this_ The <em>user data</em> to be passed to the resolved function.
/// @param args An heterogeneous sequence of arguments.
///
template <typename Args, typename... E>
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<void*>
(static_cast<void(*)(void*, Args)>(&detail::inherit_constructor<Args, E...>)),
(&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 <typename D, typename TupleArgs, typename... E, std::size_t ... S>
template <typename D, typename... E, std::size_t ... S>
Eo_Class const* create_class(eina::index_sequence<S...>)
{
static const Eo_Class* my_class = NULL;
@ -299,14 +129,12 @@ Eo_Class const* create_class(eina::index_sequence<S...>)
op_descs[detail::operation_description_size<E...>::value].func =
reinterpret_cast<void*>
(
static_cast<void(*)(Eo*, Inherit_Private_Data*, void*, TupleArgs)>
(&detail::inherit_constructor_impl<D, TupleArgs, E...>)
&detail::inherit_constructor_impl
);
op_descs[detail::operation_description_size<E...>::value].api_func =
reinterpret_cast<void*>
(
static_cast<void(*)(void*, TupleArgs)>
(&detail::inherit_constructor<TupleArgs, E...>)
&detail::inherit_constructor
);
op_descs[detail::operation_description_size<E...>::value].op = EO_NOOP;
op_descs[detail::operation_description_size<E...>::value].op_type = EO_OP_TYPE_REGULAR;

View File

@ -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)

View File

@ -17,7 +17,7 @@ struct ColourableCircle
: efl::eo::inherit<ColourableCircle, ::colourable>
{
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, ::colourablesquare>
{
ColourableBar()
: inherit_base(efl::eo::args<::colourablesquare>(0))
: inherit_base(::colourable::rgb_24bits_constructor(0))
{}
int colour_get()

View File

@ -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);

View File

@ -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<eolian_type> 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;
};

View File

@ -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<FOpts>(_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<F" << cb_idx++
<< ">, _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;

View File

@ -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)

View File

@ -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<n; i++)
{
if(i!=0) out << ", ";
out << "::efl::eolian::to_c(args.get<" << 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;
}

View File

@ -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 + " >";
}

View File

@ -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 }
};

View File

@ -1,2 +1,60 @@
// test EFL++ generated bindings
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <generic.eo.hh>
#include <check.h>
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);
}

View File

@ -0,0 +1,77 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include <Ecore.h>
#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"

View File

@ -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;
}
}