forked from enlightenment/efl
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.
This commit is contained in:
parent
3fd1566a08
commit
bffe42e71b
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ struct class_context
|
|||
inherit,
|
||||
inherit_native,
|
||||
structs,
|
||||
function_ptr,
|
||||
};
|
||||
wrapper_kind current_wrapper_kind;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue