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
This commit is contained in:
Lauro Moura 2019-07-30 11:05:26 -03:00 committed by Vitor Sousa
parent 1530d0386c
commit 29d24aa409
7 changed files with 124 additions and 0 deletions

View File

@ -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<bool> b = call_annotation_match

View File

@ -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))

View File

@ -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
}
}
/// <summary>Boxing class for custom marshalling of ValueType enums.
///
/// <para>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.</para>
/// </summary>
[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<ValueType, IntPtr> ManagedToNative = new Dictionary<ValueType, IntPtr>();
@ -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<Value>, IEquatable<Value>
/// <summary> Custom marshaler to convert value pointers to managed values and back,
/// without changing ownership.</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public class ValueMarshaler : ICustomMarshaler
{
/// <summary>Creates a managed value from a C pointer, whitout taking ownership of it.</summary>
@ -3000,4 +3040,49 @@ public class ValueMarshalerOwn : ICustomMarshaler
static private ValueMarshalerOwn marshaler;
}
/// <summary> Custom marshaler to convert value type pointers to managed boxed enum values
/// and back.</summary>
public class ValueTypeMarshaler : ICustomMarshaler
{
/// <summary>Creates a boxed ValueType enum value from a C pointer.</summary>
public object MarshalNativeToManaged(IntPtr pNativeData)
{
var r = ValueTypeBridge.GetManaged(pNativeData);
return new ValueTypeBox(r);
}
public static Eina.ValueType vtype;
/// <summary>Retrieves the C pointer from a given boxed enum value type.</summary>
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;
}
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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)
{

View File

@ -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;