csharp : add move tag info to EinaAccessor, EinaIterator converter

Summary:
Included commits in devs/lauromoura/remove_eina_mono-rebased
```
commit ed6679db19
Author: Lauro Moura <lauromoura@expertisesolutions.com.br>
Date:   Mon Dec 2 13:58:04 2019 -0300

    csharp: add move information to EnumerableToAccessor

    Still need to fix the converted accessor ownership, maybe by creating a
    custom accessor class that released the pinned memory when is freed.
```

ref T8486

Depends On D10878

Co-authored-by: Lauro Moura <lauromoura@expertisesolutions.com.br>

Test Plan: meson build -Dbindings=mono,cxx -Dmono-beta=true

Reviewers: YOhoho

Reviewed By: YOhoho

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T8486

Differential Revision: https://phab.enlightenment.org/D10879
This commit is contained in:
Yeongjong Lee 2019-12-17 11:34:41 -03:00 committed by Lauro Moura
parent f90a97470d
commit 8e951504f5
5 changed files with 90 additions and 51 deletions

View File

@ -759,7 +759,7 @@ struct convert_in_variable_generator
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = " << "Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ");\n"
"var " << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, var_name, context))
return false;
}
@ -770,7 +770,7 @@ struct convert_in_variable_generator
return false;
auto var_name = in_variable_name(param.param_name);
if (!as_generator(
"var " << string << " = " << "Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ");\n"
"var " << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, var_name, context))
return false;
}
@ -1291,12 +1291,6 @@ struct native_convert_out_assign_generator
).generate(sink, outvar, context))
return false;
// Iterators and Accessors can't own their content.
if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *"
|| param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *"
)
return true;
if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own))
&& !as_generator(
string << ".OwnContent = false;\n"
@ -1314,7 +1308,7 @@ struct native_convert_out_assign_generator
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ");\n"
string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
@ -1329,7 +1323,7 @@ struct native_convert_out_assign_generator
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ");\n"
string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
@ -1453,28 +1447,17 @@ struct native_convert_return_generator
.generate(sink, attributes::unused, context))
return false;
// Iterators and Accessors can't own their content.
if (ret_type.c_type != "Eina_Iterator *" && ret_type.c_type != "const Eina_Iterator *"
&& ret_type.c_type != "Eina_Accessor *" && ret_type.c_type != "const Eina_Accessor *"
)
{
if ((ret_type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own))
&& !as_generator("_ret_var.OwnContent = false; ")
.generate(sink, attributes::unused, context))
return false;
}
return as_generator("return _ret_var.Handle;")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
{
return as_generator("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var);")
return as_generator(lit("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
{
return as_generator("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var);")
return as_generator(lit("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type != "void")

View File

@ -72,7 +72,7 @@ struct to_internal_field_convert_generator
else if ((complex && (complex->outer.base_type == "iterator")))
{
if (!as_generator(
indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IEnumerableToIterator(_external_struct." << string << ");\n")
indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IEnumerableToIterator(_external_struct." << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}

View File

@ -774,21 +774,37 @@ public static class Globals
}
}
internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> enumerable)
internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> enumerable, bool isMoved)
{
if (enumerable == null)
{
throw new ArgumentException("enumerable is null", nameof(enumerable));
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
}
int i = 0;
// If we are a wrapper around an existing Eina.Accessor, we can just forward
// it and avoid unnecessary copying in non-owning transfers.
var wrappedAccessor = enumerable as Eina.Accessor<T>;
if (wrappedAccessor != null && !isMoved)
{
return wrappedAccessor.Handle;
}
var list = new List<IntPtr>();
foreach (T data in enumerable)
{
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
i++;
list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data));
}
IntPtr[] dataArray = intPtrs.ToArray();
IntPtr[] dataArray = list.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
return Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
IntPtr ret = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
if (!isMoved)
{
// FIXME Need to free ret and unpin pinnedArray in the future.
}
return ret;
}
internal static IEnumerable<T> IteratorToIEnumerable<T>(IntPtr iterator)
@ -802,22 +818,38 @@ public static class Globals
}
}
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable)
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable, bool isMoved)
{
if (enumerable == null)
{
throw new ArgumentException("enumerable is null", nameof(enumerable));
}
// If we are a wrapper around an existing Eina.Iterator, we can just forward
// it and avoid unnecessary copying in non-owning transfers.
var wrappedIterator = enumerable as Eina.Iterator<T>;
if (wrappedIterator != null && !isMoved)
{
return wrappedIterator.Handle;
}
var list = new List<IntPtr>();
//IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
foreach (T data in enumerable)
{
list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data));
}
IntPtr[] dataArray = list.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
return Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned);
IntPtr ret = Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
if (!isMoved)
{
// FIXME Need to free ret and unpin pinnedArray in the future.
}
return ret;
}
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
@ -841,8 +873,9 @@ public static class Globals
IntPtr list = IntPtr.Zero;
foreach (T data in enumerable)
{
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data));
}
// FIXME need to free `list` if the returned list is not @moved
return list;
}

View File

@ -4100,10 +4100,10 @@ class TestEinaIterator
Test.Assert(arr.Own);
Test.Assert(arr.OwnContent);
// Will take ownership of the Iterator
// Will copy the Iterator, owning the copy.
Test.Assert(t.EinaIteratorIntInOwn(itr));
Test.Assert(!itr.Own);
Test.Assert(itr.Own);
Test.Assert(arr.Own);
// Content must continue to be owned by the array
Test.Assert(arr.OwnContent);
@ -4224,7 +4224,7 @@ class TestEinaIterator
Test.Assert(t.EinaIteratorStrInOwn(itr));
Test.Assert(!itr.Own);
Test.Assert(itr.Own);
Test.Assert(arr.Own);
Test.Assert(arr.OwnContent);
@ -4344,7 +4344,8 @@ class TestEinaIterator
Test.Assert(t.EinaIteratorStrshareInOwn(itr));
Test.Assert(!itr.Own);
// Moving collections currently copy them, should not reflect on managed objects.
Test.Assert(itr.Own);
Test.Assert(arr.Own);
Test.Assert(arr.OwnContent);
@ -4464,7 +4465,7 @@ class TestEinaIterator
Test.Assert(t.EinaIteratorObjInOwn(itr));
Test.Assert(!itr.Own);
Test.Assert(itr.Own);
Test.Assert(arr.Own);
Test.Assert(arr.OwnContent);

View File

@ -257,25 +257,47 @@ class TestVariables
class TestEoAccessors
{
public static void basic_eo_accessors()
private static void do_eo_accessors(IEnumerable<int> accessor)
{
var obj = new Dummy.TestObject();
Eina.List<int> lst = new Eina.List<int>();
lst.Append(4);
lst.Append(3);
lst.Append(2);
lst.Append(5);
IEnumerable<int> acc = obj.CloneAccessor(lst.GetAccessor());
var zipped = acc.Zip(lst, (first, second) => new Tuple<int, int>(first, second));
IEnumerable<int> acc = obj.CloneAccessor(accessor);
var zipped = acc.Zip(accessor, (first, second) => new Tuple<int, int>(first, second));
foreach (Tuple<int, int> pair in zipped)
{
Test.AssertEquals(pair.Item1, pair.Item2);
}
lst.Dispose();
obj.Dispose();
}
public static void eina_eo_accessors()
{
Eina.List<int> lst = new Eina.List<int>();
lst.Append(4);
lst.Append(3);
lst.Append(2);
lst.Append(5);
// FIXME: Replace the first accessor with the list once Eina.List implements Eina.IList
do_eo_accessors(lst.GetAccessor());
lst.Dispose();
}
public static void managed_eo_accessors()
{
var obj = new Dummy.TestObject();
List<int> lst = new List<int>();
lst.Add(-1);
lst.Add(1);
lst.Add(4);
lst.Add(42);
do_eo_accessors(lst);
}
}
class TestEoFinalize