eolian_cxx: Fix: Using binding type for @out parameter instead of native type
authorVitor Sousa <vitorsousasilva@gmail.com>
Tue, 25 Nov 2014 18:18:08 +0000 (16:18 -0200)
committerVitor Sousa <vitorsousasilva@gmail.com>
Mon, 5 Jan 2015 17:52:27 +0000 (15:52 -0200)
No longer reverting to the native type when the parameter has "@out"
direction.

Added "is_out" member variable to eolian_type class.
With that, generators can keep track of the direction of the parameters.
Also added helper functions "type_is_out" and "type_is_complex".

Created "to_native" functions in eo_cxx_interop.hh to convert binding types
from C++ arguments to the actual C function arguments.
Added static assertions in these functions to enforce compatibility
between the binding and the native type (Required by @out parameters).

Reworked the overload of the "to_c" function for eo::base derivated
objects. Now there is a overload that rely in the compatibility
between the native type and the wrapper, enabling a wrapper to be used as
an output parameter.

src/bin/eolian_cxx/eolian_wrappers.hh
src/bindings/eo_cxx/eo_cxx_interop.hh
src/lib/eolian_cxx/eo_types.hh
src/lib/eolian_cxx/grammar/type_generator.hh

index 3dcb5e3..d563793 100644 (file)
@@ -348,7 +348,9 @@ parameter_type(Eolian_Function_Parameter const& parameter,
    assert(!type.empty());
    if (parameter_is_out(parameter))
      {
-        type = { efl::eolian::type_to_native(type) };
+        if (type.front().native == "char *")
+          type = { efl::eolian::type_to_native(type) };
+        type.front().is_out = true;
         type.front().native += "*";
      }
    if (parameter_is_const(parameter, func_type))
index fa3e44b..d829296 100644 (file)
@@ -13,12 +13,6 @@ namespace efl { namespace eolian {
 
 //// From C++ to C
 
-inline Eo*
-to_c(efl::eo::base const& x)
-{
-   return x._eo_ptr();
-}
-
 inline const char*
 to_c(std::string const& x)
 {
@@ -45,10 +39,38 @@ to_c(bool* x)
 }
 
 template <typename T>
-T to_c(T const& v, typename std::enable_if<!std::is_base_of<efl::eo::base, T>::value>::type* = 0)
+T to_c(T const& v, typename std::enable_if<!std::is_convertible<T*, efl::eo::base*>::value>::type* = 0)
 {
    return v;
 }
+
+template <typename T>
+Eo* to_c(T const& v, typename std::enable_if<std::is_convertible<T*, efl::eo::base*>::value>::type* = 0)
+{
+   return v._eo_ptr();
+}
+
+template <typename T>
+Eo** to_c(T* v, typename std::enable_if<std::is_convertible<T*, efl::eo::base*>::value>::type* = 0)
+{
+   static_assert(sizeof(T) == sizeof(Eo*), "");
+   return static_cast<Eo**>(static_cast<void*>(v));
+}
+
+template <typename R, typename T>
+R to_native(T const& v)
+{
+   static_assert(sizeof(T) == sizeof(R), "");
+   return v.native_handle();
+}
+
+template <typename R, typename T>
+R to_native(T* v)
+{
+  static_assert(sizeof(T) == sizeof(typename std::remove_pointer<R>::type), "");
+  return static_cast<R>(static_cast<void*>(v));
+}
+
     
 //// From C to C++
 
index 9223779..15f88e2 100644 (file)
@@ -33,6 +33,7 @@ struct eolian_type
      , category(unknown_)
      , is_const(false)
      , is_own(false)
+     , is_out(false)
      , binding()
      , includes()
    {}
@@ -47,6 +48,7 @@ struct eolian_type
      , category(category_)
      , is_const(is_const_)
      , is_own(is_own_)
+     , is_out(false)
      , binding(binding_)
      , includes(includes_)
    {
@@ -66,6 +68,7 @@ struct eolian_type
    category_type category;
    bool is_const;
    bool is_own;
+   bool is_out;
    std::string binding;
    includes_container_type includes;
 };
@@ -94,6 +97,19 @@ type_is_binding(eolian_type_instance const& type)
    return type_is_binding(type.front());
 }
 
+inline bool
+type_is_out(eolian_type const& type)
+{
+   return type.is_out;
+}
+
+inline bool
+type_is_out(eolian_type_instance const& type)
+{
+   assert(!type.empty());
+   return type_is_out(type.front());
+}
+
 inline eolian_type
 type_to_native(eolian_type const& type)
 {
@@ -122,6 +138,13 @@ type_is_complex(eolian_type const& type)
    return type.category == eolian_type::complex_;
 }
 
+inline bool
+type_is_complex(eolian_type_instance const& type_ins)
+{
+   assert(!type_ins.empty());
+   return type_is_complex(type_ins.front());
+}
+
 template <typename T>
 inline bool
 type_is_callback(T const&);
index fcd1600..94e91c0 100644 (file)
@@ -47,10 +47,12 @@ operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x)
    std::string res;
    for (auto rit = x._list.rbegin(), last = x._list.rend(); rit != last; ++rit)
      {
-        if (type_is_complex(*rit))
-          res = (*rit).binding + "< " + res + " >";
+        eolian_type const& t = *rit;
+        if (type_is_complex(t))
+          res = t.binding + "< " + res + " >" + (t.is_out ? "*" : "");
         else
-          res = type_is_binding(*rit) ? (*rit).binding : (*rit).native;
+          res = type_is_binding(t) ? t.binding + (t.is_out ? "*" : "")
+                                   : t.native;
      }
    assert(!res.empty());
    return out << res;
@@ -191,6 +193,8 @@ 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)
          << ", " << parameter_no_ref_type(x._type, x._varname) << " >()";
+   else if (type_is_complex(x._type) && type_is_binding(x._type))
+     out << "efl::eolian::to_native<" << c_type(x._type) << ">(" << x._varname << ")";
    else if (type_is_binding(x._type))
      out << "efl::eolian::to_c(" << x._varname << ")";
    else