From 45bb858b493bc5fac4ddbdc023c6513d4ce143f2 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Fri, 7 Jul 2017 17:38:54 -0300 Subject: eina_mono: Use DisposableIntPtr to free array data Plus minor fixes (integer size, support types other than ints in arrays, etc) --- src/bindings/mono/eina_mono/eina_value.cs | 59 ++++++++++++++++-------------- src/lib/efl_mono/efl_custom_exports_mono.c | 2 +- src/tests/efl_mono/Value.cs | 29 +++++++++++++++ 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index 574d513f8c..8b9643318d 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -66,7 +66,7 @@ static internal class UnsafeNativeMethods { [DllImport("eflcustomexportsmono")] [return: MarshalAsAttribute(UnmanagedType.U1)] - internal static extern bool eina_value_array_append_wrapper(IntPtr handle, int data); + internal static extern bool eina_value_array_append_wrapper(IntPtr handle, IntPtr data); [DllImport("eflcustomexportsmono")] [return: MarshalAsAttribute(UnmanagedType.U1)] @@ -535,7 +535,9 @@ public class Value : IDisposable, IComparable, IEquatable // Array methods public bool Append(object o) { SanityChecks(); - return eina_value_array_append_wrapper(this.Handle, (int)o); + using (DisposableIntPtr marshalled_value = MarshalValue(o)) { + return eina_value_array_append_wrapper(this.Handle, marshalled_value.Handle); + } } public object this[int i] @@ -551,23 +553,19 @@ public class Value : IDisposable, IComparable, IEquatable } set { SanityChecks(); - IntPtr marshalled_value = MarshalValue(value); - - if (!eina_value_array_set_wrapper(this.Handle, i, marshalled_value)) { - - if (GetValueSubType().IsString()) - Marshal.FreeHGlobal(marshalled_value); + using (DisposableIntPtr marshalled_value = MarshalValue(value)) + { + if (!eina_value_array_set_wrapper(this.Handle, i, marshalled_value.Handle)) { - uint size = eina_value_array_count_wrapper(this.Handle); + uint size = eina_value_array_count_wrapper(this.Handle); - if (i >= size) - throw new System.ArgumentOutOfRangeException($"Index {i} is larger than max array index {size-1}"); + if (i >= size) + throw new System.ArgumentOutOfRangeException( + $"Index {i} is larger than max array index {size-1}"); - throw new SetItemFailedException($"Failed to set item at index {i}"); + throw new SetItemFailedException($"Failed to set item at index {i}"); + } } - - if (GetValueSubType().IsString()) - Marshal.FreeHGlobal(marshalled_value); } } @@ -579,39 +577,46 @@ public class Value : IDisposable, IComparable, IEquatable return ValueTypeBridge.GetManaged(native_subtype); } - private IntPtr MarshalValue(object value) + private DisposableIntPtr MarshalValue(object value) { + IntPtr ret = IntPtr.Zero; + bool shouldFree = false; switch(GetValueSubType()) { case ValueType.Int32: { - int x = (int)value; - return new IntPtr(x); + int x = Convert.ToInt32(value); + ret = new IntPtr(x); } + break; case ValueType.UInt32: { - uint x = (uint)value; - return new IntPtr((int)x); + uint x = Convert.ToUInt32(value); + ret = new IntPtr((int)x); } + break; case ValueType.String: { string x = value as string; if (x == null) - return IntPtr.Zero; - // Warning: Caller will have ownership of this memory. - return Marshal.StringToHGlobalAnsi(x); + ret = IntPtr.Zero; + else { + ret = Marshal.StringToHGlobalAnsi(x); + shouldFree = true; + } } - default: - return IntPtr.Zero; + break; } + + return new DisposableIntPtr(ret, shouldFree); } private object UnMarshalPtr(IntPtr data) { switch(GetValueSubType()) { case ValueType.Int32: - return Convert.ToInt32(data.ToInt64()); + return Convert.ToInt32(data.ToInt32()); case ValueType.UInt32: - return Convert.ToUInt32(data.ToInt64()); + return Convert.ToUInt32(data.ToInt32()); case ValueType.String: return Marshal.PtrToStringAuto(data); default: diff --git a/src/lib/efl_mono/efl_custom_exports_mono.c b/src/lib/efl_mono/efl_custom_exports_mono.c index dc6bb81bd0..4b66ac55f3 100644 --- a/src/lib/efl_mono/efl_custom_exports_mono.c +++ b/src/lib/efl_mono/efl_custom_exports_mono.c @@ -332,7 +332,7 @@ EAPI Eina_Bool eina_value_array_get_wrapper(const Eina_Value *array, int i, void return eina_value_array_get(array, i, output); } -EAPI Eina_Bool eina_value_array_set_wrapper(const Eina_Value *array, int i, void *value) +EAPI Eina_Bool eina_value_array_set_wrapper(Eina_Value *array, int i, void *value) { return eina_value_array_set(array, i, value); } diff --git a/src/tests/efl_mono/Value.cs b/src/tests/efl_mono/Value.cs index 4a7aaf06ec..c49514c51b 100644 --- a/src/tests/efl_mono/Value.cs +++ b/src/tests/efl_mono/Value.cs @@ -336,6 +336,35 @@ public static class TestEinaValue { Test.AssertEquals((int)array[1], 1); Test.AssertEquals((int)array[2], 5); Test.AssertEquals((int)array[3], 42); + + array[0] = 1984; + array[1] = -42; + + Test.AssertEquals((int)array[0], 1984); + Test.AssertEquals((int)array[1], -42); + Test.AssertEquals((int)array[2], 5); + Test.AssertEquals((int)array[3], 42); + } + + using(eina.Value array = new eina.Value(eina.ValueType.Array, eina.ValueType.UInt32)) { + Test.Assert(array.Append(2)); + Test.AssertEquals((uint)array[0], (uint)2); + Test.AssertRaises(() => array[0] = -1); + } + + using(eina.Value array = new eina.Value(eina.ValueType.Array, eina.ValueType.String)) { + + Test.Assert(array.Append("hello")); + Test.Assert(array.Append("world")); + + Test.AssertEquals((string)array[0], "hello"); + Test.AssertEquals((string)array[1], "world"); + + array[0] = "efl"; + array[1] = "rocks"; + + Test.AssertEquals((string)array[0], "efl"); + Test.AssertEquals((string)array[1], "rocks"); } Test.AssertRaises(() => { -- cgit v1.2.1