felipealmeida pushed a commit to branch master.

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

commit bffe42e71ba12292d4969bba729e67ddf03cc111
Author: Lauro Moura <[email protected]>
Date:   Wed Mar 21 22:39:17 2018 -0300

    csharp: Support argument marshalling in func ptrs
    
    Function pointers now go through the same argument marshalling pipeline
    as normal functions.
    
    This will enable interfaces like Efl.Ui.Format to work properly.
---
 src/Makefile_Efl_Mono.am                           |  3 +-
 .../eolian_mono/eolian/mono/function_blacklist.hh  |  1 -
 .../eolian_mono/eolian/mono/function_helpers.hh    | 10 +++---
 .../eolian_mono/eolian/mono/function_pointer.hh    | 40 ++++++++++++++++------
 .../eolian_mono/eolian/mono/generation_contexts.hh |  1 +
 src/examples/elementary/efl_ui_slider_mono.cs      | 11 ++++++
 src/tests/efl_mono/FunctionPointerMarshalling.cs   | 31 +++++++++++++++++
 src/tests/efl_mono/libefl_mono_native_test.c       |  7 ++++
 src/tests/efl_mono/test_testing.eo                 | 14 ++++++++
 9 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am
index beb287ce3f..45928f977a 100644
--- a/src/Makefile_Efl_Mono.am
+++ b/src/Makefile_Efl_Mono.am
@@ -429,6 +429,7 @@ TESTS += tests/efl_mono/mono_test_driver.sh
 
 tests_efl_mono_efl_mono_SOURCES = \
      tests/efl_mono/Main.cs \
+     tests/efl_mono/TestUtils.cs \
      tests/efl_mono/BasicDirection.cs \
      tests/efl_mono/Eina.cs \
      tests/efl_mono/Eldbus.cs \
@@ -437,11 +438,11 @@ tests_efl_mono_efl_mono_SOURCES = \
      tests/efl_mono/Evas.cs \
      tests/efl_mono/Events.cs \
      tests/efl_mono/FunctionPointers.cs \
+     tests/efl_mono/FunctionPointerMarshalling.cs \
      tests/efl_mono/Parts.cs \
      tests/efl_mono/Strbuf.cs \
      tests/efl_mono/Strings.cs \
      tests/efl_mono/Structs.cs \
-     tests/efl_mono/TestUtils.cs \
      tests/efl_mono/Value.cs \
      tests/efl_mono/ValueEolian.cs
 
diff --git a/src/bin/eolian_mono/eolian/mono/function_blacklist.hh 
b/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
index b2d712c6ac..f3ec3011d5 100644
--- a/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
@@ -27,7 +27,6 @@ inline bool is_function_blacklisted(std::string const& c_name)
     || c_name == "efl_ui_focus_user_parent_get"
     || c_name == "efl_canvas_object_scale_get" // duplicated signature
     || c_name == "efl_canvas_object_scale_set" // duplicated signature
-    || c_name == "efl_ui_format_cb_set"
     || c_name == "efl_access_parent_get"
     || c_name == "efl_access_name_get"
     || c_name == "efl_access_name_set"
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh 
b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
index 2b8c912d44..acfe850032 100644
--- a/src/bin/eolian_mono/eolian/mono/function_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
@@ -10,13 +10,7 @@
 #include "grammar/list.hpp"
 #include "grammar/alternative.hpp"
 #include "grammar/attribute_reorder.hpp"
-/* #include "type.hh" */
-/* #include "marshall_type.hh" */
 #include "parameter.hh"
-#include "function_pointer.hh"
-/* #include "keyword.hh" */
-/* #include "using_decl.hh" */
-/* #include "generation_contexts.hh" */
 
 namespace eolian_mono {
 
@@ -164,6 +158,10 @@ struct native_function_definition_epilogue_parameterized
   {
     return {&klass};
   }
+  native_function_definition_epilogue_generator const 
operator()(attributes::klass_def const* klass=nullptr) const
+  {
+    return {klass};
+  }
 } const native_function_definition_epilogue;
 
 struct function_definition_epilogue_terminal
diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh 
b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
index 0890edcb51..2c0c193c33 100644
--- a/src/bin/eolian_mono/eolian/mono/function_pointer.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
@@ -6,7 +6,9 @@
 #include <vector>
 #include <string>
 
+#include "function_helpers.hh"
 #include "documentation.hh"
+#include "generation_contexts.hh"
 
 namespace eolian_mono {
 
@@ -21,7 +23,7 @@ static bool 
is_function_ptr_blacklisted(attributes::function_def const& func, st
 
   std::string name = full_name.str();
 
-  return name == "Efl.Ui.Format_Func_Cb";
+  return false;
 }
 
 struct function_pointer {
@@ -30,23 +32,29 @@ struct function_pointer {
    {
       // FIXME export Typedecl in eolian_cxx API
       std::vector<std::string> namespaces =  escape_namespace(namesp);
+      auto funcptr_ctx = 
context_add_tag(class_context{class_context::function_ptr}, context);
+
+      std::string return_type;
+      
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type),
 f.return_type, context))
+        return false;
 
       if (is_function_ptr_blacklisted(f, namesp))
         return true;
 
       auto open_namespace = *("namespace " << string << " {") << "\n";
-      if(!as_generator(open_namespace).generate(sink, namespaces, 
add_lower_case_context(context))) return false;
+      if(!as_generator(open_namespace).generate(sink, namespaces, 
add_lower_case_context(funcptr_ctx))) return false;
 
       // C# visible delegate
       if (!as_generator(documentation
                   << "public delegate " << type << " " << string
                   << "(" << (parameter % ", ") << ");\n")
-              .generate(sink, std::make_tuple(f, f.return_type, 
escape_keyword(f.name), f.parameters), context))
+              .generate(sink, std::make_tuple(f, f.return_type, 
escape_keyword(f.name), f.parameters), funcptr_ctx))
           return false;
       // "Internal" delegate, 1-to-1 with the Unamaged function type
-      if (!as_generator("internal delegate " << type << " " << string // 
public?
-                  << "Internal(IntPtr data, " << (parameter % ", ") << ");\n")
-              .generate(sink, std::make_tuple(f.return_type, 
escape_keyword(f.name), f.parameters), context))
+      if (!as_generator(marshall_native_annotation(true)
+                  << "internal delegate " << marshall_type(true) << " " << 
string // public?
+                  << "Internal(IntPtr data" << *grammar::attribute_reorder<-1, 
-1>((", " << marshall_native_annotation << " " << marshall_parameter)) << 
");\n")
+              .generate(sink, std::make_tuple(f.return_type, f.return_type, 
escape_keyword(f.name), f.parameters), funcptr_ctx))
           return false;
 
       std::string f_name = escape_keyword(f.name);
@@ -72,21 +80,31 @@ struct function_pointer {
 
                   << scope_tab << "internal " << type << " ManagedCb(" << 
(parameter % ",") << ")\n"
                   << scope_tab << "{\n"
-                  << scope_tab << scope_tab << (f.return_type.c_type != "void" 
? "return ": "") << "_cb(_cb_data, " << (argument_invocation_no_conversion % ", 
") << ");\n"
+                  << function_definition_preamble << "_cb(_cb_data, " << 
(argument_invocation % ", ") << ");\n"
+                  << function_definition_epilogue
                   << scope_tab << "}\n\n"
 
-                  << scope_tab << "internal static " << type << " Cb(IntPtr 
cb_data, " << (parameter % ", ") << ")\n"
+
+                  << scope_tab << marshall_native_annotation(true)
+                  << scope_tab << "internal static " << marshall_type(true) << 
" Cb(IntPtr cb_data" << *grammar::attribute_reorder<-1, -1>((", " << 
marshall_native_annotation << " " << marshall_parameter)) << ")\n"
                   << scope_tab << "{\n"
                   << scope_tab << scope_tab << "GCHandle handle = 
GCHandle.FromIntPtr(cb_data);\n"
                   << scope_tab << scope_tab << string << " cb = (" << string 
<< ")handle.Target;\n"
-                  << scope_tab << scope_tab << (f.return_type.c_type != "void" 
? "return " : "") << "cb(" << (argument_invocation_no_conversion % ", ") << 
");\n"
+                  << native_function_definition_preamble
+                  << scope_tab << scope_tab << "try {\n"
+                  << scope_tab << scope_tab << scope_tab <<  (return_type != " 
void" ? "_ret_var = " : "") << "cb(" << (native_argument_invocation % ", ") << 
");\n"
+                  << scope_tab << scope_tab << "} catch (Exception e) {\n"
+                  << scope_tab << scope_tab << scope_tab << 
"eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
+                  << scope_tab << scope_tab << scope_tab << 
"eina.Error.Set(eina.Error.EFL_ERROR);\n"
+                  << scope_tab << scope_tab << "}\n"
+                  << native_function_definition_epilogue(nullptr)
                   << scope_tab << "}\n"
                   << "}\n"
-                  ).generate(sink, std::make_tuple(f.return_type, 
f.parameters, f.parameters, f.return_type, f.parameters, f_name, f_name, 
f.parameters), context))
+                  ).generate(sink, std::make_tuple(f.return_type, 
f.parameters, f, f.parameters, f, f.return_type, f.return_type, f.parameters, 
f_name, f_name, f, f.parameters, f), funcptr_ctx))
           return false;
 
       auto close_namespace = *(lit("} ")) << "\n";
-      if(!as_generator(close_namespace).generate(sink, namespaces, context)) 
return false;
+      if(!as_generator(close_namespace).generate(sink, namespaces, 
funcptr_ctx)) return false;
 
       return true;
    }
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh 
b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
index 8563afcb12..d7e31ddae2 100644
--- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
+++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
@@ -11,6 +11,7 @@ struct class_context
         inherit,
         inherit_native,
         structs,
+        function_ptr,
     };
     wrapper_kind current_wrapper_kind;
 };
diff --git a/src/examples/elementary/efl_ui_slider_mono.cs 
b/src/examples/elementary/efl_ui_slider_mono.cs
index d458104cc9..64c31ab921 100644
--- a/src/examples/elementary/efl_ui_slider_mono.cs
+++ b/src/examples/elementary/efl_ui_slider_mono.cs
@@ -15,6 +15,16 @@ public class Example
         return button;
     }
 
+    public static void Formatter(eina.Strbuf buf, eina.Value val){
+        double ratio;
+        if (val.Get(out ratio)) {
+            buf.Append($"{(int)(ratio*100)}%");
+        } else {
+            buf.Append("Error");
+        }
+    }
+
+
 #if WIN32 // Passed to the C# compiler with -define:WIN32
     // Mono on Windows by default uses multi-thread apartments for COM stuff 
while
     // OLE - used by ecore win32 DnD requires single threading for COM.
@@ -41,6 +51,7 @@ public class Example
 
         efl.ui.Progressbar bar = new efl.ui.ProgressbarConcrete(box);
         bar.SetSize(new eina.Size2D(W, H));
+        bar.SetFormatCb(Formatter);
 
         efl.ui.Slider slider = new efl.ui.SliderConcrete(box);
         slider.SetSize(new eina.Size2D(W, H));
diff --git a/src/tests/efl_mono/FunctionPointerMarshalling.cs 
b/src/tests/efl_mono/FunctionPointerMarshalling.cs
new file mode 100644
index 0000000000..e7627a87f1
--- /dev/null
+++ b/src/tests/efl_mono/FunctionPointerMarshalling.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace TestSuite
+{
+
+class TestFunctionPointerMarshalling
+{
+    public static void func_pointer_marshalling()
+    {
+        test.Testing obj = new test.TestingConcrete();
+        bool called = false;
+        eina.Strbuf buf = new eina.Strbuf();
+        string argument = "Some String";
+        eina.Value v = new eina.Value(eina.ValueType.String);
+        v.Set(argument);
+        string reference = new 
string(argument.ToCharArray().Reverse().ToArray());
+
+        obj.CallFormatCb(buf, v, (eina.Strbuf ibuf, eina.Value val) => {
+            called = true;
+            string str = null;
+            val.Get(out str);
+            buf.Append(new string(str.ToCharArray().Reverse().ToArray()));
+        });
+
+        Test.Assert(called, "Callback was not called");
+        Test.AssertEquals(reference, buf.Steal());
+    }
+}
+}
diff --git a/src/tests/efl_mono/libefl_mono_native_test.c 
b/src/tests/efl_mono/libefl_mono_native_test.c
index f16c8957c3..fff2173ae8 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.c
+++ b/src/tests/efl_mono/libefl_mono_native_test.c
@@ -3756,6 +3756,13 @@ void _test_testing_call_append_to_strbuf(Eo * obj, 
EINA_UNUSED Test_Testing_Data
     test_testing_append_to_strbuf(obj, buf, str);
 }
 
+void _test_testing_call_format_cb(EINA_UNUSED Eo *obj, EINA_UNUSED 
Test_Testing_Data *pd, Eina_Strbuf *buf, const Eina_Value value,
+                               void *func_data, Test_FormatCb func, 
Eina_Free_Cb func_free_cb)
+{
+    func(func_data, buf, value);
+    func_free_cb(func_data);
+}
+
 #include "test_testing.eo.c"
 #include "test_numberwrapper.eo.c"
 
diff --git a/src/tests/efl_mono/test_testing.eo 
b/src/tests/efl_mono/test_testing.eo
index 5d1e7aa503..9a9aa0f2d1 100644
--- a/src/tests/efl_mono/test_testing.eo
+++ b/src/tests/efl_mono/test_testing.eo
@@ -81,6 +81,13 @@ function Test.SimpleCb {
    return: int;
 };
 
+function Test.FormatCb {
+   params {
+      @in str: strbuf;
+      @in value: const(any_value);
+   }
+};
+
 class Test.Testing (Efl.Object, Efl.Part) {
 
    parts {
@@ -1569,6 +1576,13 @@ class Test.Testing (Efl.Object, Efl.Part) {
          }
       }
 
+      call_format_cb {
+         params {
+            @in str: strbuf;
+            @in value: const(any_value);
+            @in func: Test.FormatCb;
+         }
+      }
    }
    implements {
       class.constructor;

-- 


Reply via email to