eolian_cxx: Fix callback handling on generated wrappers
authorVitor Sousa <vitorsousasilva@gmail.com>
Wed, 19 Nov 2014 15:59:21 +0000 (13:59 -0200)
committerVitor Sousa <vitorsousasilva@gmail.com>
Mon, 5 Jan 2015 17:52:27 +0000 (15:52 -0200)
Added callbacks to the event EO_EV_DEL for deleting heap-allocated
function objects. This will enforce that the allocated memory,
necessary for maintaining these callable objects alive, is freed at
least when the underlaying Eo object is destroyed.

Functions and constructor methods are now able to have multiple
callback types.

Removed some unused generators, since they become inconsistent now that
functions are required to handle multiple callback types.

Allocating callback objects in the constructor methods instead of
delaying it until the final constructor is called.

Created some generators to avoid code repetition.

Now the generator parameters_forward_to_c replicate the behavior of the
generator parameters_list. The generator parameters_list was, then,
removed since it have a less intuitive name.

Added a TODO comment regarding the behaviour of simple not translating
callbacks that are not followed by a user data pointer.

The generator parameter_type was moved from "parameters_generator.hh" to
"type_generator.hh" for more consistency and convenience.

src/bindings/eo_cxx/eo_cxx_interop.hh
src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
src/lib/eolian_cxx/grammar/inheritance_base_generator.hh
src/lib/eolian_cxx/grammar/parameters_generator.hh
src/lib/eolian_cxx/grammar/type_generator.hh

index 174d543..fa3e44b 100644 (file)
@@ -234,6 +234,15 @@ C get_callback()
      (tag<typename callback_args_type<C>::type>());
 }
 
+template <typename F>
+Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED
+                                , Eo_Event_Description const* e EINA_UNUSED
+                                , void* event_info EINA_UNUSED)
+{
+   delete (F*) data;
+   return EO_CALLBACK_CONTINUE;
+}
+
 } } // namespace efl { namespace eolian {
 
 #endif // EFL_EOLIAN_INTEROP_HH
index f02ca7b..c7a9bbb 100644 (file)
@@ -104,12 +104,25 @@ inline std::ostream&
 operator<<(std::ostream& out, constructor_functor_type_decl const& x)
 {
    out << constructor_functor_type_name(x._ctor);
-   auto cb_it = parameters_find_callback(x._ctor.params);
-   if(cb_it != x._ctor.params.cend())
+
+   if (parameters_count_callbacks(x._ctor.params) == 0)
+     return out;
+
+   bool comma = false;
+   out << "<";
+   auto first = x._ctor.params.cbegin(), last = x._ctor.params.cend();
+   for(auto it = first; it != last; ++it)
      {
-        out << "<F>";
+        if (type_is_callback((*it).type) && it+1 != last)
+          {
+             if (comma)
+               out << ", ";
+             else
+               comma = true;
+             out << template_parameter_type((*it).type, (*it).name);
+          }
      }
-   return out;
+   return out << ">";
 }
 
 struct functors_constructor_methods
@@ -127,17 +140,24 @@ operator<<(std::ostream& out, functors_constructor_methods const& x)
    for (it = first; it != last; ++it)
      {
         eo_constructor const& c = *it;
-        auto cb_it = parameters_find_callback(c.params);
-        bool has_callback = (cb_it != c.params.cend());
 
         // Struct declaration
-        if(has_callback)
-          {
-             out << tab(1) << "template <typename F>" << endl;
-          }
-        out << tab(1) << "struct " << constructor_functor_type_name(c) << endl
+        out << template_parameters_declaration(c.params, 1)
+            << tab(1) << "struct " << constructor_functor_type_name(c) << endl
             << tab(1) << "{" << endl;
 
+        // Callbacks typedefs
+        out << parameters_cxx_generic(c.params,
+                 [](param_data d)
+                 {
+                    if (d.is_cb)
+                      d.out << tab(2)
+                            << parameter_remove_reference_typedef(d.type, d.name)
+                            << endl;
+                 }
+               )
+            << endl;
+
         // Struct constructor
         out << tab(2) << constructor_functor_type_name(c) << "("
             << parameters_declaration(c.params) << ")"
@@ -148,7 +168,13 @@ operator<<(std::ostream& out, functors_constructor_methods const& x)
                         d.out << endl << tab(3) << ": ";
                      else
                         d.out << ", ";
-                     d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
+
+                     if (d.is_cb)
+                       d.out << callback_tmp(d.name) << "(new "
+                             << template_parameter_type(d.type, d.name)
+                             << "(" << parameter_forward(d.type, d.name) << "))";
+                     else
+                       d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
                   }
                )
             << endl
@@ -156,21 +182,22 @@ operator<<(std::ostream& out, functors_constructor_methods const& x)
 
         // Struct operator()
         out << tab(2) << "void operator()()" << endl
-            << tab(2) << "{" << endl;
-        if (has_callback)
-          {
-             out << tab(3) << "typedef typename std::remove_reference<F>::type function_type;" << endl
-                 << tab(3) << "function_type* _tmp_f = new F(this->" << (*cb_it).name << ");" << endl;
-          }
-        out << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl
+            << tab(2) << "{" << endl
+            << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl
             << tab(2) << "}" << endl;
 
         // Struct member variables
-        out << tab(1) << "private:" << endl
+        out << endl
             << parameters_cxx_generic(c.params,
                   [](param_data d)
                   {
-                     d.out << tab(2) << parameter_type(d.type) << " " << d.name << ";" << endl;
+                     d.out << tab(2);
+                     if (d.is_cb)
+                       d.out << parameter_no_ref_type(d.type, d.name) << "* "
+                             << callback_tmp(d.name);
+                     else
+                       d.out << parameter_type(d.type, d.name) << " " << d.name;
+                     d.out << ";" << endl;
                   }
                );
 
@@ -197,12 +224,9 @@ operator<<(std::ostream& out, functions_constructor_methods const& x)
      {
         eo_constructor const& c = *it;
 
-        out << comment(c.comment, 1);
-
-        unsigned cb_count = parameters_count_callbacks(c.params);
-        if(cb_count)
-          out << tab(1) << "template <typename F>" << endl;
-        out << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "("
+        out << comment(c.comment, 1)
+            << template_parameters_declaration(c.params, 1)
+            << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "("
             << parameters_declaration(c.params) << ")" << endl
             << tab(1) << "{" << endl
             << tab(2) << "return " << constructor_functor_type_decl(c) << "("
@@ -228,26 +252,50 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
    // TODO Require constructor methods of all base classes ?
    //
 
+   unsigned cb_count = 0;
+
    constructors_container_type::const_iterator it,
      first = x._cls.constructors.cbegin(),
      last = x._cls.constructors.cend();
-
    for (it = first; it != last; ++it)
      {
-        unsigned cb_count = parameters_count_callbacks((*it).params);
-        if(cb_count)
+        cb_count += parameters_count_callbacks((*it).params);
+     }
+
+   if (cb_count != 0)
+     {
+        out << tab(1) << "template <";
+        for (unsigned i = 0; i != cb_count; ++i)
           {
-             out << tab(1) << "template <typename F>" << endl;
-             break;
+             if (i != 0)
+               out << ", ";
+             out << "typename F" << i;
           }
+        out << ">" << endl;
      }
 
    out << tab(1) << x._cls.name << "(";
-   for (it = first; it != last; ++it)
-     {
-        out << constructor_functor_type_decl(*it)
-            << " _c" << (it-first) << ", ";
-     }
+   {
+      unsigned cb_idx = 0;
+      for (it = first; it != last; ++it)
+        {
+           out << constructor_functor_type_name(*it);
+
+           if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
+             {
+                out << "<"
+                    << parameters_cxx_generic((*it).params,
+                         [&cb_idx](param_data d)
+                         {
+                            if (d.is_cb)
+                              d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
+                         })
+                    << ">";
+             }
+           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(";
    for (it = first; it != last; ++it)
@@ -292,40 +340,6 @@ operator<<(std::ostream& out, constructor_eo const& x)
    return out;
 }
 
-struct constructors
-{
-   eo_class const& _cls;
-   constructors(eo_class const& cls)
-     : _cls(cls)
-   {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, constructors const& x)
-{
-   constructors_container_type::const_iterator it,
-     first = x._cls.constructors.cbegin(),
-     last = x._cls.constructors.cend();
-   for (it = first; it != last; ++it)
-     {
-        eo_constructor const& ctor = *it;
-        out << comment(ctor.comment, 1);
-        if (parameters_count_callbacks(ctor.params))
-          out << tab(1) << "template <typename F>" << endl;
-        out << tab(1)
-            << x._cls.name
-            << '(' << parameters_declaration(ctor.params)
-            << (ctor.params.size() > 0 ? ", " : "")
-            << "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl
-            << tab(2) << ": " << class_name(x._cls.name)
-            << "(_c" << (it - first) << "(" << constructor_parameters_list(ctor.params)
-            << (ctor.params.size() > 0 ? ", " : "")
-            << "_p))" << endl
-            << tab(1) << "{}" << endl << endl;
-     }
-   return out;
-}
-
 struct copy_constructor
 {
    eo_class const& _cls;
@@ -363,48 +377,6 @@ operator<<(std::ostream& out, destructor const& x)
    return out;
 }
 
-struct eo_class_constructors
-{
-   eo_class const& _cls;
-   eo_class_constructors(eo_class const& cls) : _cls(cls) {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, eo_class_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)
-     {
-        if (parameters_count_callbacks((*it).params))
-          out << tab(1) << "template <typename F>" << endl;
-        out << tab(1)
-            << "static Eo* _c" << (it - first) << "("
-            << parameters_declaration((*it).params)
-            << ((*it).params.size() > 0 ? ", " : "")
-            << "efl::eo::parent_type _p"
-            << ')' << endl
-            << tab(1) << "{" << endl;
-
-        parameters_container_type::const_iterator callback_iter =
-          parameters_find_callback((*it).params);
-        if (callback_iter != (*it).params.cend())
-          {
-             out << tab(2)
-                 << "typedef typename std::remove_reference<F>::type function_type;" << endl
-                 << "function_type* _tmp_f = new F(std::forward<F>("
-                 << (*callback_iter).name << "));"
-                 << endl;
-          }
-        out << tab(2) << "return eo_add_ref("
-            << x._cls.eo_name << ", _p._eo_raw, " << (*it).name
-            << "(" << parameters_list((*it).params) << "));" << endl
-            << tab(1) << "}" << endl << endl;
-     }
-   return out;
-}
-
 struct function_call_constructor_methods
 {
    eo_class const& _cls;
@@ -414,31 +386,78 @@ struct function_call_constructor_methods
 inline std::ostream&
 operator<<(std::ostream& out, function_call_constructor_methods const& x)
 {
+   unsigned cb_count = 0;
+
    constructors_container_type::const_iterator it,
      first = x._cls.constructors.cbegin(),
      last = x._cls.constructors.cend();
    for (it = first; it != last; ++it)
      {
-        unsigned cb_count = parameters_count_callbacks((*it).params);
-        if (cb_count)
+        unsigned param_cb_count = parameters_count_callbacks((*it).params);
+        for (unsigned i = 0; i != param_cb_count; ++i)
           {
-             out << tab(1) << "template <typename F>" << endl;
-             break;
+             if(cb_count == 0)
+               out << tab(1) << "template <";
+             else
+               out << ", ";
+             out << "typename F" << cb_count++;
           }
      }
+   if (cb_count != 0)
+     out << ">" << endl;
+
+   unsigned cb_idx = 0;
    out << tab(1) << "static Eo* _ctors_call(";
    for (it = first; it != last; ++it)
      {
-        out << constructor_functor_type_decl(*it) << " _c" << (it-first) << ", ";
+        out << constructor_functor_type_name(*it);
+
+        if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
+          {
+             out << "<"
+                 << parameters_cxx_generic((*it).params,
+                      [&cb_idx](param_data d)
+                      {
+                         if (d.is_cb)
+                           d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
+                      })
+                 << ">";
+          }
+        out << " _c" << (it-first) << ", ";
      }
+   assert(cb_idx == cb_count);
+
    out << "efl::eo::parent_type _p)" << endl
        << tab(1) << "{" << endl
-       << tab(2) << "return eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw, ";
+       << 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) << "(); ";
      }
-   out << ");" << endl
+   out << ");" << endl << endl;
+
+   cb_idx = 0;
+   for (it = first; it != last; ++it)
+     {
+        if (parameters_count_callbacks((*it).params) == 0)
+          continue;
+
+        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);
+
+   out << tab(2) << "return _ret_eo;" << endl
        << tab(1) << "}" << endl << endl;
 
    return out;
index d9c1ab9..9c48106 100644 (file)
@@ -24,7 +24,7 @@ operator<<(std::ostream& out, function_call const& x)
    bool is_void = function_is_void(x._func);
    return out << (!is_void ? "_tmp_ret = " : "")
               << "::" << x._func.impl
-              << "(" << parameters_list(x._func.params) << ")";
+              << "(" << parameters_forward_to_c(x._func.params) << ")";
 }
 
 struct function
@@ -39,8 +39,7 @@ operator<<(std::ostream& out, function const& x)
    eo_function const& func = x._func;
 
    out << comment(x._func.comment, 1);
-   if (parameters_count_callbacks(x._func.params) == 1)
-     out << tab(1) << "template <typename F>" << endl;
+   out << template_parameters_declaration(func.params, 1);
 
    if (function_is_static(func))
      out << tab(1) << "static ";
@@ -55,16 +54,7 @@ operator<<(std::ostream& out, function const& x)
      out << tab(2)
          << func.ret.front().native << " _tmp_ret;" << endl;
 
-   parameters_container_type::const_iterator callback_iter =
-     parameters_find_callback(func.params);
-   if (callback_iter != func.params.cend())
-     {
-       out << tab(2)
-           << "typedef typename std::remove_reference<F>::type function_type;" << endl
-           << tab(2) << "function_type* _tmp_f = new function_type(std::forward<F>("
-           << (*callback_iter).name << "));"
-           << endl;
-     }
+   out << callbacks_heap_alloc("_eo_ptr()", func.params, 2);
 
    out << tab(2)
        << "eo_do(_eo_ptr(), " << function_call(x._func) << ");" << endl;
index 778ec51..36d0821 100644 (file)
@@ -155,8 +155,8 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x)
    eo_function const& func = x._func;
    bool is_void = function_is_void(func);
 
-   if (parameters_count_callbacks(func.params) == 1)
-     out << tab(2) << "template <typename F>" << tab(2) << endl;
+   if (parameters_count_callbacks(func.params))
+     out << template_parameters_declaration(func.params, 2) << tab(2);
    else
      out << tab(2) << "virtual ";
 
@@ -168,12 +168,8 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x)
    if (!is_void)
      out << tab(3) << func.ret.front().native << " _tmp_ret = {};"  << endl;
 
-   parameters_container_type::const_iterator
-     callback_iter = parameters_find_callback(func.params);
-   if (callback_iter != func.params.cend())
-     out << tab(3) << "typedef typename std::remove_reference<F>::type function_type;" << endl
-         << tab(3) << "function_type* _tmp_f = new function_type(std::forward<F>("
-         << (*callback_iter).name << "));" << endl;
+   out << callbacks_heap_alloc("static_cast<T*>(this)->_eo_ptr()", func.params, 3)
+       << endl;
 
    out << tab(3)
        << "eo_do_super(static_cast<T*>(this)->_eo_ptr()," << endl
@@ -291,8 +287,7 @@ struct inheritance_extension_function
 inline std::ostream&
 operator<<(std::ostream& out, inheritance_extension_function const& x)
 {
-   if (parameters_count_callbacks(x._func.params) == 1)
-     out << tab(1) << "template <typename F>" << endl;
+   out << template_parameters_declaration(x._func.params, 1);
 
    bool is_void = function_is_void(x._func);
    out << tab(2)
@@ -307,16 +302,8 @@ operator<<(std::ostream& out, inheritance_extension_function const& x)
         out << tab(3) << x._func.ret.front().native << " _tmp_ret = {};"  << endl;
      }
 
-   parameters_container_type::const_iterator callback_iter =
-     parameters_find_callback(x._func.params);
-   if (callback_iter != x._func.params.cend())
-     {
-       out << tab(2)
-           << "typedef typename std::remove_reference<F>::type function_type;" << endl
-           << "function_type* _tmp_f = new function_type(std::forward<F>("
-           << (*callback_iter).name << "));"
-           << endl;
-     }
+   out << callbacks_heap_alloc("static_cast<U*>(this)->_eo_ptr()", x._func.params, 2)
+       << endl;
 
    out << tab(3) << "eo_do(static_cast<U*>(this)->_eo_ptr(), "
        << function_call(x._func) << ");" << endl;
index 5492859..f608479 100644 (file)
 namespace efl { namespace eolian { namespace grammar {
 
 struct
-parameter_type
-{
-   eolian_type_instance const& _type;
-   parameter_type(eolian_type_instance const& t)
-     : _type(t)
-   {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, parameter_type const& x)
-{
-   if(type_is_callback(x._type))
-      out << "F";
-   else
-      out << reinterpret_type(x._type);
-   return out;
-}
-
-struct
 parameter_forward
 {
    eolian_type_instance const& _type;
@@ -45,7 +26,7 @@ operator<<(std::ostream& out, parameter_forward const& x)
 {
    if (type_is_callback(x._type))
      {
-        out << "std::forward<F>(" << x._name << ")";
+        out << "std::forward<" << template_parameter_type(x._type, x._name) << ">(" << x._name << ")";
      }
    else
      out << x._name;
@@ -110,6 +91,134 @@ parameters_cxx_generic(parameters_container_type const& params, T fparam)
 }
 
 struct
+callback_tmp
+{
+   std::string const& _name;
+   callback_tmp(std::string const& name)
+     : _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_tmp const& x)
+{
+   return out << "_tmp_" << x._name;
+}
+
+struct
+callback_parameter_heap_alloc
+{
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   int _tab;
+   callback_parameter_heap_alloc(eolian_type_instance const& type, std::string const& name, int tab)
+     : _type(type)
+     , _name(name)
+     , _tab(tab)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_parameter_heap_alloc const& x)
+{
+   out << tab(x._tab) << parameter_remove_reference_typedef(x._type, x._name) << endl
+       << tab(x._tab) << parameter_no_ref_type(x._type, x._name) << "* "
+       << callback_tmp(x._name) << " = new "
+       << parameter_no_ref_type(x._type, x._name) << "(std::forward<"
+       << template_parameter_type(x._type, x._name) << ">(" << x._name << "));" << endl;
+   return out;
+}
+
+struct
+callback_parameter_free_ev_add
+{
+   std::string const& _eo_raw_expr;
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   callback_parameter_free_ev_add(std::string const& eo_raw_expr, eolian_type_instance const& type, std::string const& name)
+     : _eo_raw_expr(eo_raw_expr)
+     , _type(type)
+     , _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_parameter_free_ev_add const& x)
+{
+   out << "eo_do(" << x._eo_raw_expr
+       << ", eo_event_callback_add(EO_EV_DEL, &efl::eolian::free_callback_calback<"
+       << parameter_no_ref_type(x._type, x._name) << ">, "
+       << callback_tmp(x._name) << "));";
+   return out;
+}
+
+struct
+callbacks_heap_alloc
+{
+   std::string const& _eo_raw_expr;
+   parameters_container_type const& _params;
+   int _tab;
+   callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, int tab)
+     : _eo_raw_expr(eo_raw_expr)
+     , _params(params)
+     , _tab(tab)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callbacks_heap_alloc const& x)
+{
+   auto first = x._params.cbegin(), last = x._params.cend();
+   for (auto it = first; it != last; ++it)
+     {
+        if (type_is_callback((*it).type) && it+1 != last)
+          {
+             out << callback_parameter_heap_alloc((*it).type, (*it).name, x._tab)
+                 << tab(x._tab)
+                 << callback_parameter_free_ev_add(x._eo_raw_expr, (*it).type, (*it).name)
+                 << endl << endl;
+             ++it; // skip next.
+          }
+     }
+   return out;
+}
+
+struct
+template_parameters_declaration
+{
+   parameters_container_type const& _params;
+   int _tab;
+   template_parameters_declaration(parameters_container_type const& params, int tab)
+     : _params(params)
+     , _tab(tab)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, template_parameters_declaration const& x)
+{
+   if (parameters_count_callbacks(x._params) == 0)
+     return out;
+
+   bool comma = false;
+   out << tab(x._tab) << "template <";
+   auto first = x._params.cbegin(), last = x._params.cend();
+   for (auto it = first; it != last; ++it)
+     {
+        if (type_is_callback((*it).type) && it+1 != last)
+          {
+             if (comma)
+               out << ", ";
+             else
+               comma = true;
+             out << "typename " << template_parameter_type((*it).type, (*it).name);
+             ++it; // skip next.
+          }
+     }
+   return out << ">" << endl;
+}
+
+struct
 parameters_declaration
 {
    parameters_container_type const& _params;
@@ -131,8 +240,7 @@ operator<<(std::ostream& out, parameters_declaration const& x)
         //      and does not have a following userdata pointer ?
         if (type_is_callback((*it).type) && it+1 != last)
           {
-            out << "F && " << (*it).name;
-            assert(it+1 != last);
+            out << template_parameter_type((*it).type, (*it).name) << " && " << (*it).name;
             ++it; // skip next.
           }
         else
@@ -188,40 +296,6 @@ operator<<(std::ostream& out, parameters_types const& x)
 }
 
 struct
-parameters_list
-{
-   parameters_container_type const& _params;
-   parameters_list(parameters_container_type const& params)
-     : _params(params)
-   {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, parameters_list const& x)
-{
-   auto first = x._params.cbegin(), last = x._params.cend();
-   for (auto it = first; it != last; ++it)
-     {
-        if (it != first)
-          out << ", ";
-        if (type_is_callback((*it).type))
-          {
-            if(it + 1 != last)
-              {
-                out << to_c((*it).type, (*it).name)
-                    << ", _tmp_f";
-                ++it; // skip next
-              }
-            else
-              out << it->name;
-          }
-        else
-          out << to_c((*it).type, (*it).name);
-     }
-   return out;
-}
-
-struct
 parameters_c_list
 {
    parameters_container_type const& _params;
@@ -266,35 +340,6 @@ operator<<(std::ostream& out, parameters_cxx_list const& x)
 }
 
 struct
-constructor_parameters_list
-{
-   parameters_container_type const& _params;
-   constructor_parameters_list(parameters_container_type const& params)
-     : _params(params)
-   {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, constructor_parameters_list const& x)
-{
-   auto first = x._params.cbegin(),
-     last = x._params.cend();
-   for (auto it = first; it != last; ++it)
-     {
-        if (it != first)
-          out << ", ";
-        if (type_is_callback((*it).type) && it + 1 != last)
-          {
-             out << "std::forward<F>(" << (*it).name << ")";
-             ++it; // skip next.
-          }
-        else
-          out << (*it).name;
-     }
-   return out;
-}
-
-struct
 parameters_forward
 {
    parameters_container_type const& _params;
@@ -337,10 +382,17 @@ operator<<(std::ostream& out, parameters_forward_to_c const& x)
      {
         if (it != first)
           out << ", ";
-        if (type_is_callback((*it).type) && it + 1 != last)
+        if (type_is_callback((*it).type))
           {
-             out << to_c((*it).type, (*it).name) << ", _tmp_f";
-             ++it; // skip next
+             // TODO: Is it correct to simple not translate the callback type
+             //       when it is the last paramenter?
+             if(it + 1 != last)
+               {
+                  out << to_c((*it).type, (*it).name) << ", " << callback_tmp((*it).name);
+                  ++it; // skip next
+               }
+             else
+               out << (*it).name;
           }
         else
           out << to_c((*it).type, (*it).name);
index 8584a57..fcd1600 100644 (file)
@@ -77,6 +77,81 @@ operator<<(std::ostream& out, type_ownership const& x)
    return out << ">()";
 }
 
+struct
+template_parameter_type
+{
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   template_parameter_type(eolian_type_instance const& type, std::string const& name)
+     : _type(type)
+     , _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, template_parameter_type const& x)
+{
+   return out << "F_" << x._name;
+}
+
+struct
+parameter_type
+{
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   parameter_type(eolian_type_instance const& t, std::string const& name)
+     : _type(t)
+     , _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_type const& x)
+{
+   if(type_is_callback(x._type))
+      out << template_parameter_type(x._type, x._name);
+   else
+      out << reinterpret_type(x._type);
+   return out;
+}
+
+struct
+parameter_no_ref_type
+{
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   parameter_no_ref_type(eolian_type_instance const& type, std::string const& name)
+     : _type(type)
+     , _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_no_ref_type const& x)
+{
+   return out << "_no_ref_" << parameter_type(x._type, x._name);
+}
+
+struct
+parameter_remove_reference_typedef
+{
+   eolian_type_instance const& _type;
+   std::string const& _name;
+   parameter_remove_reference_typedef(eolian_type_instance const& type, std::string const& name)
+     : _type(type)
+     , _name(name)
+   {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_remove_reference_typedef const& x)
+{
+   out << "typedef typename std::remove_reference<"
+       << parameter_type(x._type, x._name)
+       << ">::type " << parameter_no_ref_type(x._type, x._name) << ";";
+   return out;
+}
+
 struct to_cxx
 {
    eolian_type_instance const& _type;
@@ -114,7 +189,8 @@ inline std::ostream&
 operator<<(std::ostream& out, to_c const& x)
 {
    if (type_is_callback(x._type))
-     out << "efl::eolian::get_callback<" << type_to_native_str(x._type) << ", function_type>()";
+     out << "efl::eolian::get_callback<" << type_to_native_str(x._type)
+         << ", " << parameter_no_ref_type(x._type, x._varname) << " >()";
    else if (type_is_binding(x._type))
      out << "efl::eolian::to_c(" << x._varname << ")";
    else