forked from enlightenment/efl
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:
parent
f90a97470d
commit
8e951504f5
|
@ -759,7 +759,7 @@ struct convert_in_variable_generator
|
||||||
return false;
|
return false;
|
||||||
auto var_name = in_variable_name(param.param_name);
|
auto var_name = in_variable_name(param.param_name);
|
||||||
if (!as_generator(
|
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))
|
).generate(sink, var_name, context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -770,7 +770,7 @@ struct convert_in_variable_generator
|
||||||
return false;
|
return false;
|
||||||
auto var_name = in_variable_name(param.param_name);
|
auto var_name = in_variable_name(param.param_name);
|
||||||
if (!as_generator(
|
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))
|
).generate(sink, var_name, context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1291,12 +1291,6 @@ struct native_convert_out_assign_generator
|
||||||
).generate(sink, outvar, context))
|
).generate(sink, outvar, context))
|
||||||
return false;
|
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))
|
if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own))
|
||||||
&& !as_generator(
|
&& !as_generator(
|
||||||
string << ".OwnContent = false;\n"
|
string << ".OwnContent = false;\n"
|
||||||
|
@ -1314,7 +1308,7 @@ struct native_convert_out_assign_generator
|
||||||
return false;
|
return false;
|
||||||
auto outvar = out_variable_name(param.param_name);
|
auto outvar = out_variable_name(param.param_name);
|
||||||
if (!as_generator(
|
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))
|
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1329,7 +1323,7 @@ struct native_convert_out_assign_generator
|
||||||
return false;
|
return false;
|
||||||
auto outvar = out_variable_name(param.param_name);
|
auto outvar = out_variable_name(param.param_name);
|
||||||
if (!as_generator(
|
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))
|
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1453,28 +1447,17 @@ struct native_convert_return_generator
|
||||||
.generate(sink, attributes::unused, context))
|
.generate(sink, attributes::unused, context))
|
||||||
return false;
|
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;")
|
return as_generator("return _ret_var.Handle;")
|
||||||
.generate(sink, attributes::unused, context);
|
.generate(sink, attributes::unused, context);
|
||||||
}
|
}
|
||||||
else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
|
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);
|
.generate(sink, attributes::unused, context);
|
||||||
}
|
}
|
||||||
else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
|
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);
|
.generate(sink, attributes::unused, context);
|
||||||
}
|
}
|
||||||
else if (ret_type.c_type != "void")
|
else if (ret_type.c_type != "void")
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct to_internal_field_convert_generator
|
||||||
else if ((complex && (complex->outer.base_type == "iterator")))
|
else if ((complex && (complex->outer.base_type == "iterator")))
|
||||||
{
|
{
|
||||||
if (!as_generator(
|
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))
|
.generate(sink, std::make_tuple(field_name, field_name), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
if (enumerable == null)
|
||||||
|
{
|
||||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
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)
|
foreach (T data in enumerable)
|
||||||
{
|
{
|
||||||
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
|
list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data));
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
IntPtr[] dataArray = intPtrs.ToArray();
|
IntPtr[] dataArray = list.ToArray();
|
||||||
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
|
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)
|
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)
|
if (enumerable == null)
|
||||||
|
{
|
||||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
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>();
|
var list = new List<IntPtr>();
|
||||||
//IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
|
|
||||||
|
|
||||||
foreach (T data in enumerable)
|
foreach (T data in enumerable)
|
||||||
{
|
{
|
||||||
list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data));
|
list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr[] dataArray = list.ToArray();
|
IntPtr[] dataArray = list.ToArray();
|
||||||
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
|
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned);
|
||||||
return Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
|
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)
|
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
|
||||||
|
@ -841,8 +873,9 @@ public static class Globals
|
||||||
IntPtr list = IntPtr.Zero;
|
IntPtr list = IntPtr.Zero;
|
||||||
foreach (T data in enumerable)
|
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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4100,10 +4100,10 @@ class TestEinaIterator
|
||||||
Test.Assert(arr.Own);
|
Test.Assert(arr.Own);
|
||||||
Test.Assert(arr.OwnContent);
|
Test.Assert(arr.OwnContent);
|
||||||
|
|
||||||
// Will take ownership of the Iterator
|
// Will copy the Iterator, owning the copy.
|
||||||
Test.Assert(t.EinaIteratorIntInOwn(itr));
|
Test.Assert(t.EinaIteratorIntInOwn(itr));
|
||||||
|
|
||||||
Test.Assert(!itr.Own);
|
Test.Assert(itr.Own);
|
||||||
Test.Assert(arr.Own);
|
Test.Assert(arr.Own);
|
||||||
// Content must continue to be owned by the array
|
// Content must continue to be owned by the array
|
||||||
Test.Assert(arr.OwnContent);
|
Test.Assert(arr.OwnContent);
|
||||||
|
@ -4224,7 +4224,7 @@ class TestEinaIterator
|
||||||
|
|
||||||
Test.Assert(t.EinaIteratorStrInOwn(itr));
|
Test.Assert(t.EinaIteratorStrInOwn(itr));
|
||||||
|
|
||||||
Test.Assert(!itr.Own);
|
Test.Assert(itr.Own);
|
||||||
Test.Assert(arr.Own);
|
Test.Assert(arr.Own);
|
||||||
Test.Assert(arr.OwnContent);
|
Test.Assert(arr.OwnContent);
|
||||||
|
|
||||||
|
@ -4344,7 +4344,8 @@ class TestEinaIterator
|
||||||
|
|
||||||
Test.Assert(t.EinaIteratorStrshareInOwn(itr));
|
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.Own);
|
||||||
Test.Assert(arr.OwnContent);
|
Test.Assert(arr.OwnContent);
|
||||||
|
|
||||||
|
@ -4464,7 +4465,7 @@ class TestEinaIterator
|
||||||
|
|
||||||
Test.Assert(t.EinaIteratorObjInOwn(itr));
|
Test.Assert(t.EinaIteratorObjInOwn(itr));
|
||||||
|
|
||||||
Test.Assert(!itr.Own);
|
Test.Assert(itr.Own);
|
||||||
Test.Assert(arr.Own);
|
Test.Assert(arr.Own);
|
||||||
Test.Assert(arr.OwnContent);
|
Test.Assert(arr.OwnContent);
|
||||||
|
|
||||||
|
|
|
@ -257,25 +257,47 @@ class TestVariables
|
||||||
|
|
||||||
class TestEoAccessors
|
class TestEoAccessors
|
||||||
{
|
{
|
||||||
public static void basic_eo_accessors()
|
private static void do_eo_accessors(IEnumerable<int> accessor)
|
||||||
{
|
{
|
||||||
var obj = new Dummy.TestObject();
|
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)
|
foreach (Tuple<int, int> pair in zipped)
|
||||||
{
|
{
|
||||||
Test.AssertEquals(pair.Item1, pair.Item2);
|
Test.AssertEquals(pair.Item1, pair.Item2);
|
||||||
}
|
}
|
||||||
lst.Dispose();
|
|
||||||
obj.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
|
class TestEoFinalize
|
||||||
|
|
Loading…
Reference in New Issue