aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2019-02-06 17:50:28 -0200
committerLauro Moura <lauromoura@expertisesolutions.com.br>2019-02-06 18:38:43 -0200
commit999c1bfde8ec54310358415cbab5ab5518bce86a (patch)
treea198d987942e2b8ece220d64530c78a5bf89d35a
parentefl-mono: Remove uneeded declaration from classes. (diff)
downloadefl-devs/lauromoura/eflclass.tar.gz
efl-mono: Add an initial support for Efl.Classdevs/lauromoura/eflclass
Efl.Class (in practice, the return from the *_class_get() functions) can be used as argument to functions, like in Efl.Object.provider_find and Efl.Ui.Widget_Factory.item_class(get/set). This commits adds (partial) support by representing Efl.Class instances as System.Type in the C# API, allowing someone to do things like: `factory.ItemClass == typeof(MyFramework.MyButton)` Some issues: - User-defined classes. Currently, the Eo Efl_Class instance for a user-defined class is created upon the first instantiation of this class. This may not be enough if you want to pass your class to a factory. - Conversion back from C to C#. In the case of overriding Efl.Object.provider_find, the C# override in the binding receives an IntPtr with the Eo_Class and needs to convert to the corresponding C# System.Type. Maybe a mix of `efl_class_get_name` plus Type.GetType can work.
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh9
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_annotation.hh44
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh3
-rw-r--r--src/bindings/mono/eo_mono/iwrapper.cs41
-rw-r--r--src/bindings/mono/meson.build1
-rw-r--r--src/tests/efl_mono/Eo.cs13
-rw-r--r--src/tests/efl_mono/dummy_test_object.eo1
-rw-r--r--src/tests/efl_mono/libefl_mono_native_test.c12
8 files changed, 112 insertions, 12 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 6c02de67ed..0b1f7769ab 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -347,6 +347,15 @@ struct klass
return false;
}
+ // Copied from nativeinherit class, used when setting up providers.
+ if(!as_generator(
+ scope_tab << "public static " << (root ? "" : "new ") << " IntPtr GetEflClassStatic()\n"
+ << scope_tab << "{\n"
+ << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
+ << scope_tab << "}\n"
+ ).generate(sink, attributes::unused, inherit_cxt))
+ return false;
+
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
}
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
index 6ddb990da8..744b4f8720 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
@@ -142,12 +142,22 @@ struct marshall_annotation_visitor_generate
}
bool operator()(attributes::klass_name const& klass_name) const
{
- const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
- const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
- return as_generator
- ((is_return ? return_prefix : no_return_prefix)
- << string << ", Efl.Eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
- ).generate(sink, name_helpers::klass_full_concrete_name(klass_name), *context);
+ const char *return_prefix = is_return ? "return:" : "";
+ const char *marshal_prefix = "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(";
+
+ std::string name = name_helpers::klass_full_concrete_name(klass_name);
+
+ if (name == "Efl.Class")
+ name = "Efl.Eo.MarshalEflClass";
+ else
+ {
+ auto own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag";
+ name = "Efl.Eo.MarshalTest<" + name + ", Efl.Eo." + own + ">";
+ }
+
+ return as_generator(
+ lit("[") << return_prefix << marshal_prefix << name << "))]"
+ ).generate(sink, name, *context);
}
bool operator()(attributes::complex_type_def const& c) const
{
@@ -252,12 +262,22 @@ struct marshall_native_annotation_visitor_generate
}
bool operator()(attributes::klass_name const& klass_name) const
{
- const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
- const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
- return as_generator
- ((is_return ? return_prefix : no_return_prefix)
- << string << ", Efl.Eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
- ).generate(sink, name_helpers::klass_full_concrete_name(klass_name), *context);
+ const char *return_prefix = is_return ? "return:" : "";
+ const char *marshal_prefix = "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(";
+
+ std::string name = name_helpers::klass_full_concrete_name(klass_name);
+
+ if (name == "Efl.Class")
+ name = "Efl.Eo.MarshalEflClass";
+ else
+ {
+ auto own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag";
+ name = "Efl.Eo.MarshalTest<" + name + ", Efl.Eo." + own + ">";
+ }
+
+ return as_generator(
+ lit("[") << return_prefix << marshal_prefix << name << "))]"
+ ).generate(sink, name, *context);
}
bool operator()(attributes::complex_type_def const& c) const
{
diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh
index c449d216a5..e3eece3834 100644
--- a/src/bin/eolian_mono/eolian/mono/type_impl.hh
+++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh
@@ -309,6 +309,9 @@ struct visitor_generate
}
bool operator()(attributes::klass_name klass) const
{
+ // Efl.Class is manually handled in a custom marshall to be represented by a System.Type.
+ if (name_helpers::klass_full_concrete_name(klass) == "Efl.Class")
+ return as_generator(lit("Type")).generate(sink, attributes::unused, *context);
if(klass.type == attributes::class_type::regular || klass.type == attributes::class_type::abstract_)
return as_generator(string).generate(sink, name_helpers::klass_full_concrete_name(klass), *context);
else
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
index 2119e07106..a9334b4040 100644
--- a/src/bindings/mono/eo_mono/iwrapper.cs
+++ b/src/bindings/mono/eo_mono/iwrapper.cs
@@ -593,6 +593,47 @@ public class MarshalTest<T, U> : ICustomMarshaler
}
}
+///<summary>Marshals between System.Type instances and Eo classes (IntPtrs).</summary>
+public class MarshalEflClass : ICustomMarshaler
+{
+ public static ICustomMarshaler GetInstance(string cookie)
+ {
+ Eina.Log.Debug("MarshalTest.GetInstance cookie " + cookie);
+ return new MarshalEflClass();
+ }
+ public void CleanUpManagedData(object ManagedObj)
+ {
+ }
+
+ public void CleanUpNativeData(IntPtr pNativeData)
+ {
+ }
+
+ public int GetNativeDataSize()
+ {
+ Eina.Log.Debug("MarshalTest.GetNativeDataSize");
+ return 0;
+ }
+
+ public IntPtr MarshalManagedToNative(object ManagedObj)
+ {
+ Eina.Log.Debug("MarshalTest.MarshallManagedToNative");
+ Type t = ManagedObj as Type;
+
+ // FIXME Make it work for user-defined C# classes.
+ var method = t?.GetMethod("GetEflClassStatic",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
+
+ return (IntPtr)method?.Invoke(null, null);
+ }
+
+ public object MarshalNativeToManaged(IntPtr pNativeData)
+ {
+ Eina.Log.Debug("MarshalTest.MarshalNativeToManaged");
+ throw new NotImplementedException();
+ }
+}
+
public class StringPassOwnershipMarshaler : ICustomMarshaler {
public object MarshalNativeToManaged(IntPtr pNativeData) {
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
diff --git a/src/bindings/mono/meson.build b/src/bindings/mono/meson.build
index b9d6879998..0285522de8 100644
--- a/src/bindings/mono/meson.build
+++ b/src/bindings/mono/meson.build
@@ -14,6 +14,7 @@ mono_sublibs = [
]
blacklisted_files = [
+ 'efl_class.eo',
'efl_canvas_text.eo',
'efl_canvas_scene3d.eo',
'evas_canvas3d_camera.eo',
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index 37d4735b90..66a5ac7a5c 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -369,4 +369,17 @@ class TestConstructors
}
}
+class TestProvider
+{
+ public static void test_find_provider()
+ {
+ // Tests only the direction C# -> C
+ var tmp = new Dummy.Numberwrapper();
+ var obj = new Dummy.TestObject();
+ Dummy.Numberwrapper provider = Dummy.Numberwrapper.static_cast(obj.FindProvider(typeof(Dummy.Numberwrapper)));
+ Test.AssertEquals(provider.GetType(), typeof(Dummy.Numberwrapper));
+ Test.AssertEquals(provider.GetNumber(), 1999);
+ }
+}
+
}
diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo
index 2081f3f4e0..34d9fba76b 100644
--- a/src/tests/efl_mono/dummy_test_object.eo
+++ b/src/tests/efl_mono/dummy_test_object.eo
@@ -1671,6 +1671,7 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
class.destructor;
Efl.Object.constructor;
Efl.Part.part_get;
+ Efl.Object.provider_find;
Dummy.Test_Iface.emit_test_conflicted;
Dummy.Test_Iface.emit_nonconflicted;
Dummy.Test_Iface.iface_prop { get; set; }
diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c
index 51086216e3..ffc6712d12 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.c
+++ b/src/tests/efl_mono/libefl_mono_native_test.c
@@ -73,6 +73,7 @@ typedef struct Dummy_Test_Object_Data
Eina_List *list_for_accessor;
int setter_only;
int iface_prop;
+ Eo *provider;
} Dummy_Test_Object_Data;
typedef struct Dummy_Numberwrapper_Data
@@ -150,6 +151,9 @@ _dummy_test_object_efl_object_constructor(Eo *obj, Dummy_Test_Object_Data *pd)
pd->part_two = efl_add(DUMMY_TEST_OBJECT_CLASS, obj, efl_name_set(efl_added, "part_two"));
}
+ pd->provider = efl_add(DUMMY_NUMBERWRAPPER_CLASS, obj);
+ dummy_numberwrapper_number_set(pd->provider, 1999);
+
return obj;
}
@@ -3939,6 +3943,14 @@ int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj
return pd->iface_prop;
}
+Eo * _dummy_test_object_efl_object_provider_find(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd, const Efl_Class *klass)
+{
+ EINA_LOG_ERR("klass: %p, NUMBERWRAPPER: %p", klass, DUMMY_NUMBERWRAPPER_CLASS);
+ if (klass == DUMMY_NUMBERWRAPPER_CLASS)
+ return pd->provider;
+ return efl_provider_find(efl_super(obj, DUMMY_TEST_OBJECT_CLASS), klass);
+}
+
/// Dummy.Child
static Efl_Object *