jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=5425baa9061753356d450a3c736669341e1b1570

commit 5425baa9061753356d450a3c736669341e1b1570
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Wed Nov 22 16:54:57 2017 +0900

    cxx: Add support for function pointers
    
    This was tested on the function pointer Efl.Ui.Format_Func_Cb
---
 src/bin/eolian_cxx/eolian_cxx.cc                   | 115 ++++++++++++++++++--
 src/bindings/cxx/eo_cxx/eo_cxx_interop.hh          |  20 +---
 src/lib/eolian_cxx/grammar/converting_argument.hpp |  24 +---
 .../eolian_cxx/grammar/function_declaration.hpp    |   8 ++
 src/lib/eolian_cxx/grammar/function_definition.hpp |  19 +++-
 src/lib/eolian_cxx/grammar/header.hpp              |   1 +
 src/lib/eolian_cxx/grammar/klass_def.hpp           |  60 +++++++++-
 src/lib/eolian_cxx/grammar/parameter.hpp           |  29 ++++-
 .../grammar/type_function_declaration.hpp          | 121 +++++++++++++++++++++
 src/lib/eolian_cxx/grammar/types_definition.hpp    |  38 +++++++
 10 files changed, 386 insertions(+), 49 deletions(-)

diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 3fab179cae..b67d0442b9 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -25,6 +25,7 @@
 #include "grammar/klass_def.hpp"
 #include "grammar/header.hpp"
 #include "grammar/impl_header.hpp"
+#include "grammar/types_definition.hpp"
 
 namespace eolian_cxx {
 
@@ -58,7 +59,8 @@ opts_check(eolian_cxx::options_type const& opts)
 }
 
 static bool
-generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
+generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts,
+         std::string const& cpp_types_header)
 {
    std::string header_decl_file_name = opts.out_file.empty()
      ? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file;
@@ -143,9 +145,9 @@ generate(const Eolian_Class* klass, 
eolian_cxx::options_type const& opts)
          }
      };
    klass_function(klass);
-   
+
    cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh"));
-   
+
    std::string guard_name;
    as_generator(*(efl::eolian::grammar::string << "_") << 
efl::eolian::grammar::string << "_EO_HH")
      .generate(std::back_insert_iterator<std::string>(guard_name)
@@ -153,12 +155,13 @@ generate(const Eolian_Class* klass, 
eolian_cxx::options_type const& opts)
                , efl::eolian::grammar::context_null{});
 
    std::tuple<std::string, std::set<std::string>&, std::set<std::string>&
+              , std::string const&
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               > attributes
-   {guard_name, c_headers, cpp_headers, klasses, forward_klasses, klasses, 
klasses};
+   {guard_name, c_headers, cpp_headers, cpp_types_header, klasses, 
forward_klasses, klasses, klasses};
 
    if(opts.out_file == "-")
      {
@@ -205,19 +208,117 @@ generate(const Eolian_Class* klass, 
eolian_cxx::options_type const& opts)
    return true;
 }
 
+static bool
+types_generate(std::string const& fname, options_type const& opts,
+               std::string& cpp_types_header)
+{
+   using namespace efl::eolian::grammar::attributes;
+
+   std::vector<function_def> functions;
+   Eina_Iterator *itr = eolian_declarations_get_by_file(fname.c_str());
+   /* const */ Eolian_Declaration *decl;
+
+   // Build list of functions with their parameters
+   while(::eina_iterator_next(itr, reinterpret_cast<void**>(&decl)))
+     {
+        Eolian_Declaration_Type dt = eolian_declaration_type_get(decl);
+        if (dt != EOLIAN_DECL_ALIAS)
+          continue;
+
+        const Eolian_Typedecl *tp = eolian_declaration_data_type_get(decl);
+        if (!tp || eolian_typedecl_is_extern(tp))
+          continue;
+
+        if (::eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
+          continue;
+
+        const Eolian_Function *func = eolian_typedecl_function_pointer_get(tp);
+        if (!func) return false;
+
+        Eina_Iterator *param_itr = eolian_function_parameters_get(func);
+        std::vector<parameter_def> params;
+
+        /* const */ Eolian_Function_Parameter *param;
+        while (::eina_iterator_next(param_itr, reinterpret_cast<void 
**>(&param)))
+          {
+             parameter_direction param_dir;
+             switch (eolian_parameter_direction_get(param))
+               {
+                /* Note: Inverted on purpose, as the direction objects are
+                 * passed is inverted (from C to C++ for function pointers).
+                 * FIXME: This is probably not right in all cases. */
+                case EOLIAN_IN_PARAM: param_dir = parameter_direction::out; 
break;
+                case EOLIAN_INOUT_PARAM: param_dir = 
parameter_direction::inout; break;
+                case EOLIAN_OUT_PARAM: param_dir = parameter_direction::in; 
break;
+                default: return false;
+               }
+
+             const Eolian_Type *param_type_eolian = 
eolian_parameter_type_get(param);
+             type_def param_type(param_type_eolian, opts.unit, 
EOLIAN_C_TYPE_PARAM);
+             std::string param_name = eolian_parameter_name_get(param);
+             std::string param_c_type = 
eolian_type_c_type_get(param_type_eolian, EOLIAN_C_TYPE_PARAM);
+             parameter_def param_def(param_dir, param_type, param_name, 
param_c_type);
+             params.push_back(std::move(param_def));
+          }
+        ::eina_iterator_free(param_itr);
+
+        const Eolian_Type *ret_type_eolian = 
eolian_function_return_type_get(func, EOLIAN_FUNCTION_POINTER);
+
+        type_def ret_type = void_;
+        if (ret_type_eolian)
+          ret_type = type_def(ret_type_eolian, opts.unit, 
EOLIAN_C_TYPE_RETURN);
+
+        /*
+        // List namespaces. Not used as function_wrapper lives in efl::eolian.
+        std::vector<std::string> namespaces;
+        Eina_Iterator *ns_itr = eolian_typedecl_namespaces_get(tp);
+        char *ns;
+        while (::eina_iterator_next(ns_itr, reinterpret_cast<void**>(&ns)))
+          namespaces.push_back(std::string(ns));
+        ::eina_iterator_free(ns_itr);
+        */
+
+        std::string name = eolian_function_name_get(func);
+        std::string c_name = eolian_typedecl_full_name_get(tp);
+        std::replace(c_name.begin(), c_name.end(), '.', '_');
+        bool beta = eolian_function_is_beta(func);
+
+        function_def def(ret_type, name, params, c_name, beta, false, true);
+        functions.push_back(std::move(def));
+     }
+   ::eina_iterator_free(itr);
+
+   if (functions.empty())
+     return true;
+
+   std::stringstream sink;
+
+   sink.write("\n", 1);
+   if (!efl::eolian::grammar::types_definition
+       .generate(std::ostream_iterator<char>(sink),
+                 functions, efl::eolian::grammar::context_null()))
+     return false;
+
+   cpp_types_header = sink.str();
+
+   return true;
+}
+
 static void
 run(options_type const& opts)
 {
    if(!opts.main_header)
      {
-       const Eolian_Class *klass = NULL;
+       const Eolian_Class *klass = nullptr;
        char* dup = strdup(opts.in_files[0].c_str());
        char* base = basename(dup);
-       klass = ::eolian_class_get_by_file(NULL, base);
+       std::string cpp_types_header;
+       klass = ::eolian_class_get_by_file(nullptr, base);
        free(dup);
        if (klass)
          {
-           if (!generate(klass, opts))
+           if (!types_generate(base, opts, cpp_types_header) ||
+               !generate(klass, opts, cpp_types_header))
              {
                EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
                  << "Error generating: " << ::eolian_class_name_get(klass)
diff --git a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh 
b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
index 662e5a7d55..9181c11875 100644
--- a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
+++ b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
@@ -61,6 +61,8 @@ template <>
 struct out_traits<void*> { typedef void*& type; };
 template <typename T>
 struct out_traits<efl::shared_future<T>> { typedef efl::shared_future<T>& 
type; };
+template <>
+struct out_traits<efl::eina::strbuf> { typedef efl::eina::strbuf_wrapper& 
type; };
 
 template <typename T>
 struct inout_traits { typedef T& type; };
@@ -291,23 +293,7 @@ auto convert_inout(V& object) -> 
decltype(impl::convert_inout_impl(object, impl:
 template <typename T, typename U, bool Own = false, typename V>
 T convert_to_c(V&& object);
 
-template <typename F, typename T>
-void* data_function_ptr_to_c(T)
-{
-  return nullptr;
-}
-
-template <typename F, typename T>
-F function_ptr_to_c()
-{
-  return nullptr;
-}
-
-template <typename F, typename T>
-Eina_Free_Cb free_function_ptr_to_c()
-{
-  return nullptr;
-}
+template <typename U, typename F, typename V=void> struct function_wrapper;
 
 namespace impl {
 
diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp 
b/src/lib/eolian_cxx/grammar/converting_argument.hpp
index 230608ffc3..eb7ef57376 100644
--- a/src/lib/eolian_cxx/grammar/converting_argument.hpp
+++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp
@@ -33,24 +33,12 @@ struct converting_argument_generator
    bool generate(OutputIterator sink, attributes::parameter_def const& param, 
Context const& ctx) const
    {
      attributes::qualifier_def qualifier = 
param.type.original_type.visit(attributes::get_qualifier_visitor{});
-     bool is_function_ptr = 
param.type.original_type.visit(this->is_function_ptr);
-     if(is_function_ptr)
-       return as_generator
-       (
-        attribute_reorder<-1, -1, 2, -1, -1, -1, -1>
-        (
-         " ::efl::eolian::data_function_ptr_to_c<" << c_type
-         << ", " << parameter_type
-         << ">(" << string << ")"
-
-         ", ::efl::eolian::function_ptr_to_c<" << c_type
-         << ", " << parameter_type
-         << ">()"
-         ", ::efl::eolian::free_function_ptr_to_c<" << c_type
-         << ", " << parameter_type
-         << ">()"
-        )
-       ).generate(sink, param, ctx);
+     if (param.type.original_type.visit(this->is_function_ptr))
+       {
+          // FIXME: This supports only one function pointer.
+          return as_generator("fw->data_to_c(), fw->func_to_c(), 
fw->free_to_c()")
+                .generate(sink, param, ctx);
+       }
      else
        return as_generator
        (
diff --git a/src/lib/eolian_cxx/grammar/function_declaration.hpp 
b/src/lib/eolian_cxx/grammar/function_declaration.hpp
index e98fbf0a3a..641ae6560c 100644
--- a/src/lib/eolian_cxx/grammar/function_declaration.hpp
+++ b/src/lib/eolian_cxx/grammar/function_declaration.hpp
@@ -1,3 +1,4 @@
+
 #ifndef EOLIAN_CXX_FUNCTION_DECLARATION_HH
 #define EOLIAN_CXX_FUNCTION_DECLARATION_HH
 
@@ -42,6 +43,13 @@ struct function_declaration_generator
             !as_generator("#ifdef " << *(string << "_") << string << "_" << 
string << "_BETA\n")
             .generate(sink, std::make_tuple(_klass_name.namespaces, 
_klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
         return false;
+
+      std::string template_statement(f.template_statement());
+      if (!template_statement.empty() &&
+          !as_generator(template_statement << " ")
+          .generate(sink, attributes::unused, ctx))
+        return false;
+
       if(!as_generator
             ("::efl::eolian::return_traits<" << grammar::type(true) << 
">::type " << string << "(" << (parameter % ", ") << ") const;\n")
             .generate(sink, std::make_tuple(f.return_type, 
escape_keyword(f.name), f.parameters), ctx))
diff --git a/src/lib/eolian_cxx/grammar/function_definition.hpp 
b/src/lib/eolian_cxx/grammar/function_definition.hpp
index 50bd9970c5..55f56216fd 100644
--- a/src/lib/eolian_cxx/grammar/function_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/function_definition.hpp
@@ -17,6 +17,7 @@
 #include "grammar/attribute_conditional.hpp"
 #include "grammar/attribute_reorder.hpp"
 #include "grammar/type_impl.hpp"
+#include "grammar/eps.hpp"
 
 namespace efl { namespace eolian { namespace grammar {
 
@@ -52,12 +53,24 @@ struct function_definition_generator
          !as_generator("#ifdef " << *(string << "_") << string << 
"_PROTECTED\n")
          .generate(sink, std::make_tuple(_klass_name.namespaces, 
_klass_name.eolian_name), add_upper_case_context(ctx)))
         return false;
-     
+
+      std::string template_statement(f.template_statement());
+      if (!template_statement.empty() &&
+          !as_generator(template_statement << "\n")
+          .generate(sink, attributes::unused, ctx))
+        return false;
+
       if(!as_generator
          ("inline ::efl::eolian::return_traits<" << grammar::type(true) << 
">::type " << string << "::" << string << "(" << (parameter % ", ") << ") 
const\n{\n")
          .generate(sink, std::make_tuple(f.return_type, 
_klass_name.eolian_name, escape_keyword(f.name), f.parameters), ctx))
         return false;
 
+      std::vector<std::string> opening_statements(f.opening_statements());
+      if (!opening_statements.empty() &&
+          !as_generator(scope_tab << *(string) << "\n")
+          .generate(sink, std::make_tuple(opening_statements), ctx))
+        return false;
+
       auto out_declaration =
         attribute_conditional([] (attributes::parameter_def const& p) -> bool
                               { return p.direction == 
attributes::parameter_direction::out; })
@@ -118,8 +131,8 @@ struct function_definition_generator
             scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", 
" << c_type
             <<
             (
-             attribute_conditional([] (attributes::type_def const& type)
-             { return 
type.original_type.visit(attributes::get_qualifier_visitor{}) & 
qualifier_info::is_own; })
+             attribute_conditional([] (attributes::type_def const& typ)
+             { return 
typ.original_type.visit(attributes::get_qualifier_visitor{}) & 
qualifier_info::is_own; })
              [
                ", true"
              ] | eps
diff --git a/src/lib/eolian_cxx/grammar/header.hpp 
b/src/lib/eolian_cxx/grammar/header.hpp
index 63a6095949..4f1df9233f 100644
--- a/src/lib/eolian_cxx/grammar/header.hpp
+++ b/src/lib/eolian_cxx/grammar/header.hpp
@@ -24,6 +24,7 @@ auto class_header =
     << "#include <Eina.hh>\n"
        "#include <Eo.hh>\n"
     << *header_include_directive // sequence<string>
+    <<  string                   // extra header <string>
     << *class_declaration          // sequence<class> | class
     << *class_forward_declaration          // sequence<class> | class
     << "\nnamespace eo_cxx {\n"
diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp 
b/src/lib/eolian_cxx/grammar/klass_def.hpp
index edfadc05bb..f7b12af578 100644
--- a/src/lib/eolian_cxx/grammar/klass_def.hpp
+++ b/src/lib/eolian_cxx/grammar/klass_def.hpp
@@ -433,6 +433,7 @@ struct function_def
   std::string filename;
   bool is_beta;
   bool is_protected;
+  bool is_function_pointer;
 
   friend inline bool operator==(function_def const& lhs, function_def const& 
rhs)
   {
@@ -442,17 +443,27 @@ struct function_def
       && lhs.c_name == rhs.c_name
       && lhs.filename == rhs.filename
       && lhs.is_beta == rhs.is_beta
-      && lhs.is_protected == rhs.is_protected;
+      && lhs.is_protected == rhs.is_protected
+      && lhs.is_function_pointer == rhs.is_function_pointer;
   }
   friend inline bool operator!=(function_def const& lhs, function_def const& 
rhs)
   {
     return !(lhs == rhs);
   }
-  
+  function_def() = default;
   function_def(type_def return_type, std::string name, 
std::vector<parameter_def> parameters
                , std::string c_name, std::string filename, bool is_beta)
     : return_type(return_type), name(name), parameters(parameters), 
c_name(c_name), filename(filename), is_beta(is_beta) {}
-  function_def() = default;
+  function_def(type_def _return_type, std::string const& _name,
+               std::vector<parameter_def> const& _parameters,
+               std::string const& _c_name,
+               bool _is_beta = false,
+               bool _is_protected = false,
+               bool _is_function_pointer = false)
+    : return_type(_return_type), name(_name), parameters(_parameters),
+      c_name(_c_name), is_beta(_is_beta), is_protected(_is_protected),
+      is_function_pointer(_is_function_pointer) {}
+
   function_def( ::Eolian_Function const* function, Eolian_Function_Type type, 
Eolian_Unit const* unit)
     : return_type(void_)
   {
@@ -517,6 +528,49 @@ struct function_def
      is_protected = eolian_function_scope_get(function, type) == 
EOLIAN_SCOPE_PROTECTED;
      is_protected = eolian_function_scope_get(function, type) == 
EOLIAN_SCOPE_PROTECTED;
   }
+
+  std::string template_statement() const
+  {
+     std::string statement;
+     char template_typename = 'F';
+     for (auto const& param : this->parameters)
+       {
+          attributes::regular_type_def const* typ =
+                
efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
+          if (typ && typ->is_function_ptr)
+            {
+               char typenam[2] = { 0, };
+               typenam[0] = template_typename++;
+               if (statement.empty())
+                 statement = std::string("template <typename ") + typenam;
+               else
+                 statement += std::string(", typename ") + typenam;
+            }
+       }
+     if (statement.empty()) return statement;
+     else return statement + ">";
+  }
+
+  std::vector<std::string> opening_statements() const
+  {
+     // FIXME: Supports only one function pointer
+     std::vector<std::string> statements;
+     char template_typename = 'F';
+     for (auto const& param : this->parameters)
+       {
+          attributes::regular_type_def const* typ =
+                
efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
+          if (typ && typ->is_function_ptr)
+            {
+               char typenam[2] = { 0, };
+               typenam[0] = template_typename++;
+               std::string statement = "auto fw = new 
::efl::eolian::function_wrapper<";
+               statement += param.c_type + ", " + typenam + ">(" + 
param.param_name + ");";
+               statements.push_back(statement);
+            }
+       }
+     return statements;
+  }
 };
 
 template <>
diff --git a/src/lib/eolian_cxx/grammar/parameter.hpp 
b/src/lib/eolian_cxx/grammar/parameter.hpp
index f9e625a514..5d8d3aef5c 100644
--- a/src/lib/eolian_cxx/grammar/parameter.hpp
+++ b/src/lib/eolian_cxx/grammar/parameter.hpp
@@ -25,6 +25,12 @@ struct parameter_type_generator
             dir = "in";
           break;
         }
+
+      attributes::regular_type_def const* typ =
+            
efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
+      if (typ && typ->is_function_ptr)
+        return as_generator("F").generate(sink, attributes::unused, context);
+
       return as_generator
         (
          " ::efl::eolian::" << string << "_traits<"
@@ -44,6 +50,8 @@ struct attributes_needed<parameter_type_generator> : 
std::integral_constant<int,
 
 parameter_type_generator const parameter_type = {};
 
+
+/* */
 struct parameter_generator
 {
    template <typename OutputIterator, typename Context>
@@ -59,9 +67,28 @@ template <>
 struct is_generator<parameter_generator> : std::true_type {};
 namespace type_traits {
 template <>
-struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> 
{};  
+struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> 
{};
 }
 parameter_generator const parameter = {};
+
+
+/* */
+struct parameter_as_argument_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, 
Context const& context) const
+   {
+      return as_generator(parameter_type << "(" << string << 
")").generate(sink, std::make_tuple(param, param.param_name), context);
+   }
+};
+
+template <>
+struct is_eager_generator<parameter_as_argument_generator> : std::true_type {};
+namespace type_traits {
+template <>
+struct attributes_needed<parameter_as_argument_generator> : 
std::integral_constant<int, 1> {};
+}
+parameter_as_argument_generator const parameter_as_argument = {};
       
 } } }
 
diff --git a/src/lib/eolian_cxx/grammar/type_function_declaration.hpp 
b/src/lib/eolian_cxx/grammar/type_function_declaration.hpp
new file mode 100644
index 0000000000..eccedf8f4a
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/type_function_declaration.hpp
@@ -0,0 +1,121 @@
+#ifndef EOLIAN_CXX_TYPE_FUNCTION_DECLARATION_HH
+#define EOLIAN_CXX_TYPE_FUNCTION_DECLARATION_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+
+#include "grammar/string.hpp"
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/type.hpp"
+#include "grammar/parameter.hpp"
+#include "grammar/keyword.hpp"
+#include "grammar/converting_argument.hpp"
+#include "grammar/eps.hpp"
+
+namespace efl { namespace eolian { namespace grammar {
+
+/** This generates the caller struct for function pointers. */
+struct type_function_declaration_generator {
+   type_function_declaration_generator() {}
+
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::function_def const& f, 
Context const& ctx) const
+   {
+      std::string guard = f.c_name + "_defined";
+
+      if (!as_generator("#ifndef " << string << "\n" <<
+                        "#define " << string << "\n")
+          .generate(sink, std::make_tuple(guard, guard), 
add_upper_case_context(ctx)))
+        return false;
+
+      // efl::eolian::function_wrapper<T, F>
+      if (!as_generator("namespace efl { namespace eolian {\n")
+          .generate(sink, attributes::unused, add_lower_case_context(ctx)))
+      return false;
+
+      if (!as_generator(
+             "template <typename F>\n"
+             "struct function_wrapper<" << string << ", F> {\n"
+             << scope_tab << "function_wrapper(F cxx_func) : 
_cxx_func(cxx_func) {}\n"
+             ).generate(sink, f.c_name, ctx))
+        return false;
+
+      if (!as_generator(
+             scope_tab << "void *data_to_c() { return static_cast<void 
*>(this); }\n"
+             << scope_tab << string << " func_to_c() const { return &caller; 
}\n"
+             << scope_tab << "Eina_Free_Cb free_to_c() const { return 
&deleter; }\n"
+             << "private:\n"
+             << scope_tab << "F _cxx_func;\n"
+             << scope_tab << "static void deleter(void *data) {\n"
+             << scope_tab << scope_tab << "delete 
static_cast<function_wrapper<" << string << ", F>*>(data);\n"
+             << scope_tab << "}\n"
+             ).generate(sink, std::make_tuple(f.c_name, f.c_name), ctx))
+        return false;
+
+      std::vector<std::string> c_args;
+      for (auto itr : f.parameters)
+        c_args.push_back(", " + itr.c_type + " " + itr.param_name);
+      if (!as_generator(
+             scope_tab << "static " << string << " caller(void *cxx_call_data"
+             << *(string) << ") {\n"
+             << scope_tab << scope_tab << "auto fw = 
static_cast<function_wrapper<"
+             << string << ", F>*>(cxx_call_data);\n"
+             ).generate(sink, std::make_tuple(f.return_type.c_type, c_args, 
f.c_name), ctx))
+        return false;
+
+      if (f.return_type != attributes::void_
+          && !as_generator(scope_tab << scope_tab << "auto __return_value =\n")
+          .generate(sink, attributes::unused, ctx))
+        return false;
+
+      if (!f.parameters.empty())
+        {
+           std::vector<attributes::parameter_def> params;
+           for (auto itr = f.parameters.begin() + 1; itr != 
f.parameters.end(); itr++)
+             params.push_back(*itr);
+           if (!as_generator(
+                  scope_tab << scope_tab << "fw->_cxx_func(" << 
parameter_as_argument << *(", " << parameter_as_argument) << ");\n"
+                  ).generate(sink, std::make_tuple(*f.parameters.begin(), 
params), ctx))
+               return false;
+        }
+
+      if (f.return_type != attributes::void_
+          && !as_generator(scope_tab << scope_tab << "return 
::efl::eolian::convert_to_c<"
+                           << type << ">(__return_value);\n")
+          .generate(sink, f.return_type, ctx))
+        return false;
+
+      if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, 
ctx))
+        return false;
+
+      if (!as_generator("};\n"
+                        "} }\n"
+                        "#endif\n\n")
+          .generate(sink, attributes::unused, ctx))
+        return false;
+
+      return true;
+   }
+};
+
+template <>
+struct is_eager_generator<type_function_declaration_generator> : 
std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed<type_function_declaration_generator> : 
std::integral_constant<int, 1> {};
+}
+
+struct type_function_declaration_terminal
+{
+  type_function_declaration_generator operator()() const
+  {
+    return type_function_declaration_generator{};
+  }
+} const type_function_declaration = {};
+
+} } }
+
+#endif
diff --git a/src/lib/eolian_cxx/grammar/types_definition.hpp 
b/src/lib/eolian_cxx/grammar/types_definition.hpp
new file mode 100644
index 0000000000..e4c40737d6
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/types_definition.hpp
@@ -0,0 +1,38 @@
+#ifndef EOLIAN_CXX_TYPES_DEFINITION_HH
+#define EOLIAN_CXX_TYPES_DEFINITION_HH
+
+#include "header_guards.hpp"
+#include "eps.hpp"
+#include "string.hpp"
+#include "sequence.hpp"
+#include "kleene.hpp"
+#include "header_include_directive.hpp"
+#include "type_function_declaration.hpp"
+
+namespace efl { namespace eolian { namespace grammar {
+
+struct types_definition_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, std::vector<attributes::function_def> 
const& functions, Context const& ctx) const
+   {
+      if(!as_generator(*(type_function_declaration()))
+            .generate(sink, functions, ctx))
+        return false;
+      return true;
+   }
+};
+
+template <>
+struct is_eager_generator<types_definition_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed<types_definition_generator> : 
std::integral_constant<int, 1> {};
+}
+
+types_definition_generator const types_definition = {};
+
+} } }
+
+#endif

-- 


Reply via email to