From 5a7f236f82764afa611a01b287995dcd46eaa762 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Tue, 30 Jul 2019 11:05:26 -0300 Subject: [PATCH] csharp: Add marshal support for Eina.ValueType Summary: It uses a custom marshaler and a helper boxing class to convert between the managed enum values and the native Eina_Value_Type pointers. To be used by future MVVM machinery. Reviewers: vitor.sousa, felipealmeida Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9443 --- .../eolian_mono/eolian/mono/marshall_annotation.hh | 6 ++ .../eolian_mono/eolian/mono/marshall_type_impl.hh | 7 ++ src/bindings/mono/eina_mono/eina_value.cs | 85 ++++++++++++++++++++++ src/lib/efl_mono/efl_custom_exports_mono.c | 3 + src/tests/efl_mono/ValueEolian.cs | 11 +++ src/tests/efl_mono/dummy_test_object.c | 5 ++ src/tests/efl_mono/dummy_test_object.eo | 7 ++ 7 files changed, 124 insertions(+) diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh index 632696d..6d56b24 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh @@ -82,6 +82,9 @@ struct marshall_annotation_visitor_generate {"strbuf", false, [&] { return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]"; }}, + {"Value_Type", false, [&] { + return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))]"; + }}, }; match const return_match_table[] = { @@ -117,6 +120,9 @@ struct marshall_annotation_visitor_generate {"strbuf", false, [&] { return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]"; }}, + {"Value_Type", false, [&] { + return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))]"; + }}, }; if(eina::optional b = call_annotation_match diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh index 8de109e..588e8c2 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh @@ -161,6 +161,13 @@ struct marshall_type_visitor_generate r.base_type = "void"; return r; }} + , {"Value_Type", nullptr, [&] + { + regular_type_def r = regular; + r.namespaces.clear(); + r.base_type = "Eina.ValueTypeBox"; + return r; + }} }; if (regular.is_struct() && !blacklist::is_struct_blacklisted(regular) && !(bool)(regular.base_qualifier & qualifier_info::is_own)) diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index cedf500..57a6157 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -3,6 +3,7 @@ #define CODE_ANALYSIS using System; +using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; using System.Collections.Generic; @@ -515,6 +516,8 @@ static internal class UnsafeNativeMethods internal static extern IntPtr type_array(); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr type_list(); + [DllImport(efl.Libs.CustomExports)] + internal static extern IntPtr type_hash(); // Optional [DllImport(efl.Libs.CustomExports)] @@ -716,6 +719,39 @@ static class ValueTypeMethods } } +/// Boxing class for custom marshalling of ValueType enums. +/// +/// As custom marshalling of enums (and other value types) is not supported, use +/// use this boxing class as an intermediate at the Marshalling API level (like in +/// marshall_type_impl.hh in the generator). User-facing API still uses Eina.ValueType +/// normally. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public class ValueTypeBox +{ + public ValueType _payload; + + public ValueTypeBox(ValueType v) + { + _payload = v; + } + + public static implicit operator ValueTypeBox(ValueType v) + { + return new ValueTypeBox(v); + } + + public static implicit operator ValueType(ValueTypeBox box) + { + if (box == null) + { + return Eina.ValueType.Empty; + } + + return box._payload; + } +} + static class ValueTypeBridge { private static Dictionary ManagedToNative = new Dictionary(); @@ -860,6 +896,9 @@ static class ValueTypeBridge ManagedToNative.Add(ValueType.List, type_list()); NativeToManaged.Add(type_list(), ValueType.List); + ManagedToNative.Add(ValueType.Hash, type_hash()); + NativeToManaged.Add(type_hash(), ValueType.Hash); + ManagedToNative.Add(ValueType.Optional, type_optional()); NativeToManaged.Add(type_optional(), ValueType.Optional); @@ -2898,6 +2937,7 @@ public class Value : IDisposable, IComparable, IEquatable /// Custom marshaler to convert value pointers to managed values and back, /// without changing ownership. +[EditorBrowsable(EditorBrowsableState.Never)] public class ValueMarshaler : ICustomMarshaler { /// Creates a managed value from a C pointer, whitout taking ownership of it. @@ -3000,4 +3040,49 @@ public class ValueMarshalerOwn : ICustomMarshaler static private ValueMarshalerOwn marshaler; } +/// Custom marshaler to convert value type pointers to managed boxed enum values +/// and back. +public class ValueTypeMarshaler : ICustomMarshaler +{ + /// Creates a boxed ValueType enum value from a C pointer. + public object MarshalNativeToManaged(IntPtr pNativeData) + { + var r = ValueTypeBridge.GetManaged(pNativeData); + return new ValueTypeBox(r); + } + public static Eina.ValueType vtype; + + /// Retrieves the C pointer from a given boxed enum value type. + public IntPtr MarshalManagedToNative(object managedObj) + { + ValueTypeBox v = (ValueTypeBox)managedObj; + return ValueTypeBridge.GetNative(v); + } + + public void CleanUpNativeData(IntPtr pNativeData) + { + } + + public void CleanUpManagedData(object managedObj) + { + } + + public int GetNativeDataSize() + { + return -1; + } + + public static ICustomMarshaler GetInstance(string cookie) + { + if (marshaler == null) + { + marshaler = new ValueTypeMarshaler(); + } + + return marshaler; + } + + static private ValueTypeMarshaler marshaler; +} + } diff --git a/src/lib/efl_mono/efl_custom_exports_mono.c b/src/lib/efl_mono/efl_custom_exports_mono.c index aa2572f..590bb4e 100644 --- a/src/lib/efl_mono/efl_custom_exports_mono.c +++ b/src/lib/efl_mono/efl_custom_exports_mono.c @@ -421,6 +421,9 @@ EAPI const Eina_Value_Type *type_array() { EAPI const Eina_Value_Type *type_list() { return EINA_VALUE_TYPE_LIST; } +EAPI const Eina_Value_Type *type_hash() { + return EINA_VALUE_TYPE_HASH; +} EAPI const Eina_Value_Type *type_error() { return EINA_VALUE_TYPE_ERROR; } diff --git a/src/tests/efl_mono/ValueEolian.cs b/src/tests/efl_mono/ValueEolian.cs index ea178d4..945228a 100644 --- a/src/tests/efl_mono/ValueEolian.cs +++ b/src/tests/efl_mono/ValueEolian.cs @@ -160,6 +160,17 @@ public static class TestEinaValueEolian { Test.AssertEquals(expected, received); Test.AssertEquals(Eina.ValueType.Int32, received.GetValueType()); } + + public static void TestEolianEinaValueTypeMarshalling() + { + var obj = new Dummy.TestObject(); + + var values = Enum.GetValues(typeof(Eina.ValueType)); + foreach (Eina.ValueType type in values) + { + Test.AssertEquals(type, obj.MirrorValueType(type)); + } + } } #pragma warning restore 1591 } diff --git a/src/tests/efl_mono/dummy_test_object.c b/src/tests/efl_mono/dummy_test_object.c index 6717b12..8ba7536 100644 --- a/src/tests/efl_mono/dummy_test_object.c +++ b/src/tests/efl_mono/dummy_test_object.c @@ -4685,6 +4685,11 @@ Efl_Object *_dummy_test_object_call_find_provider_for_iface(Eo *obj, EINA_UNUSED return efl_provider_find(obj, DUMMY_TEST_IFACE_INTERFACE); } +const Eina_Value_Type *_dummy_test_object_mirror_value_type(EINA_UNUSED const Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, const Eina_Value_Type *type) +{ + return type; +} + // Inherit int _dummy_inherit_helper_receive_dummy_and_call_int_out(Dummy_Test_Object *x) { diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo index 2273c23..4f26beb 100644 --- a/src/tests/efl_mono/dummy_test_object.eo +++ b/src/tests/efl_mono/dummy_test_object.eo @@ -1642,6 +1642,13 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface { call_find_provider_for_iface { return: Efl.Object; } + + mirror_value_type @beta @const { + params { + @in type: const(ptr(Eina.Value_Type)); + } + return: const(ptr(Eina.Value_Type)); + } } implements { Efl.Object.constructor; -- 2.7.4