csharp: Provisionally fix conversion of eina.Value

When we have an eina.Value_Native (representing an Eina_Value passed by
value) and assign it to an eina.Value (a class with an IntPtr to an
underlying Eina_Value) we copy it so the eina.Value can take ownership
and free the data normally.

A possibly better alternative would be adding an extra flag to
eina.Value (something like OwnsPointer) to check whether we should free
the struct we point to or not.
This commit is contained in:
Lauro Moura 2018-03-21 22:43:21 -03:00 committed by Felipe Magno de Almeida
parent e2fafe5b0c
commit 3fd1566a08
5 changed files with 56 additions and 1 deletions

View File

@ -325,6 +325,10 @@ static internal class UnsafeNativeMethods {
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_value_pset_wrapper(IntPtr handle, ref eina.EinaNative.Value_List ptr);
[DllImport(efl.Libs.CustomExports)]
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_value_copy(IntPtr src, IntPtr dest);
// Supported types
// 8 bits byte
@ -707,12 +711,18 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
public Value(Value_Native value)
{
this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
IntPtr tmp = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
try {
Marshal.StructureToPtr(value, this.Handle, false);
Marshal.StructureToPtr(value, tmp, false); // Can't get the address of a struct directly.
if (!eina_value_copy(tmp, this.Handle))
throw new System.InvalidOperationException("Failed to copy value to managed memory.");
} catch {
MemoryNative.Free(this.Handle);
throw;
} finally {
MemoryNative.Free(tmp);
}
this.Ownership = Ownership.Managed;
}

View File

@ -800,6 +800,16 @@ public static class TestEinaValue {
}
}
public static void TestStringThroughValue() {
// Check if Value_Native->Value doesn't try to free the pointed string.
using(eina.Value value_ptr = new eina.Value(eina.ValueType.String)) {
string payload = "Something";
value_ptr.Set(payload);
eina.Value_Native byvalue = value_ptr;
eina.Value another_value_ptr = byvalue;
}
}
// FIXME Add remaining list tests

View File

@ -109,6 +109,30 @@ public static class TestEinaValueEolian {
Test.AssertEquals(eina.Ownership.Managed, v_out.Ownership);
}
}
private class ValueHandler : test.TestingInherit
{
public eina.Value value;
public ValueHandler() : base(null)
{
value = null;
}
public override void SetValue(eina.Value value)
{
this.value = value;
}
}
public static void TestEolianEinaValueByValueConst()
{
ValueHandler obj = new ValueHandler();
using (eina.Value val = new eina.Value(eina.ValueType.String)) {
obj.CallSetValue(val);
Test.AssertEquals(val, obj.value);
}
}
}
#pragma warning restore 1591
}

View File

@ -3648,6 +3648,11 @@ void _test_testing_set_value(EINA_UNUSED Eo *obj, Test_Testing_Data *pd, Eina_Va
eina_value_copy(&value, pd->stored_value);
}
void _test_testing_call_set_value(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, const Eina_Value v)
{
test_testing_set_value(obj, v);
}
Eina_Value *_test_testing_get_value_ptr_own(EINA_UNUSED Eo *obj, Test_Testing_Data *pd)
{
Eina_Value *val = pd->stored_value;

View File

@ -1327,6 +1327,12 @@ class Test.Testing (Efl.Object, Efl.Part) {
}
}
call_set_value {
params {
value: const(any_value);
}
}
get_value_ptr_own {
return: any_value_ptr @owned;
}