diff options
author | Yeongjong Lee <yj34.lee@samsung.com> | 2019-12-17 11:34:41 -0300 |
---|---|---|
committer | Lauro Moura <lauromoura@expertisesolutions.com.br> | 2019-12-17 11:34:42 -0300 |
commit | 8e951504f584f124ba88471fc46f1e7b6d2d3639 (patch) | |
tree | 3839fc7a7e31b744cf6ed9b9b1d5acfda0ab6d55 | |
parent | f90a97470d54edb20116e55739025e71cdfbbd92 (diff) |
csharp : add move tag info to EinaAccessor, EinaIterator converter
Summary:
Included commits in devs/lauromoura/remove_eina_mono-rebased
```
commit ed6679db1901c710cc6ddb50e7001cfd20caa77a
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
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/parameter.hh | 29 | ||||
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/struct_definition.hh | 2 | ||||
-rw-r--r-- | src/bindings/mono/eo_mono/iwrapper.cs | 59 | ||||
-rw-r--r-- | src/tests/efl_mono/Eina.cs | 11 | ||||
-rw-r--r-- | src/tests/efl_mono/Eo.cs | 38 |
5 files changed, 89 insertions, 50 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh index a5a70f2bb0..210e5f22d5 100644 --- a/src/bin/eolian_mono/eolian/mono/parameter.hh +++ b/src/bin/eolian_mono/eolian/mono/parameter.hh | |||
@@ -759,7 +759,7 @@ struct convert_in_variable_generator | |||
759 | return false; | 759 | return false; |
760 | auto var_name = in_variable_name(param.param_name); | 760 | auto var_name = in_variable_name(param.param_name); |
761 | if (!as_generator( | 761 | if (!as_generator( |
762 | "var " << string << " = " << "Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ");\n" | 762 | "var " << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n" |
763 | ).generate(sink, var_name, context)) | 763 | ).generate(sink, var_name, context)) |
764 | return false; | 764 | return false; |
765 | } | 765 | } |
@@ -770,7 +770,7 @@ struct convert_in_variable_generator | |||
770 | return false; | 770 | return false; |
771 | auto var_name = in_variable_name(param.param_name); | 771 | auto var_name = in_variable_name(param.param_name); |
772 | if (!as_generator( | 772 | if (!as_generator( |
773 | "var " << string << " = " << "Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ");\n" | 773 | "var " << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n" |
774 | ).generate(sink, var_name, context)) | 774 | ).generate(sink, var_name, context)) |
775 | return false; | 775 | return false; |
776 | } | 776 | } |
@@ -1291,12 +1291,6 @@ struct native_convert_out_assign_generator | |||
1291 | ).generate(sink, outvar, context)) | 1291 | ).generate(sink, outvar, context)) |
1292 | return false; | 1292 | return false; |
1293 | 1293 | ||
1294 | // Iterators and Accessors can't own their content. | ||
1295 | if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *" | ||
1296 | || param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *" | ||
1297 | ) | ||
1298 | return true; | ||
1299 | |||
1300 | if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own)) | 1294 | if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own)) |
1301 | && !as_generator( | 1295 | && !as_generator( |
1302 | string << ".OwnContent = false;\n" | 1296 | string << ".OwnContent = false;\n" |
@@ -1314,7 +1308,7 @@ struct native_convert_out_assign_generator | |||
1314 | return false; | 1308 | return false; |
1315 | auto outvar = out_variable_name(param.param_name); | 1309 | auto outvar = out_variable_name(param.param_name); |
1316 | if (!as_generator( | 1310 | if (!as_generator( |
1317 | string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ");\n" | 1311 | string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n" |
1318 | ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) | 1312 | ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) |
1319 | return false; | 1313 | return false; |
1320 | } | 1314 | } |
@@ -1329,7 +1323,7 @@ struct native_convert_out_assign_generator | |||
1329 | return false; | 1323 | return false; |
1330 | auto outvar = out_variable_name(param.param_name); | 1324 | auto outvar = out_variable_name(param.param_name); |
1331 | if (!as_generator( | 1325 | if (!as_generator( |
1332 | string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ");\n" | 1326 | string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n" |
1333 | ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) | 1327 | ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) |
1334 | return false; | 1328 | return false; |
1335 | } | 1329 | } |
@@ -1453,28 +1447,17 @@ struct native_convert_return_generator | |||
1453 | .generate(sink, attributes::unused, context)) | 1447 | .generate(sink, attributes::unused, context)) |
1454 | return false; | 1448 | return false; |
1455 | 1449 | ||
1456 | // Iterators and Accessors can't own their content. | ||
1457 | if (ret_type.c_type != "Eina_Iterator *" && ret_type.c_type != "const Eina_Iterator *" | ||
1458 | && ret_type.c_type != "Eina_Accessor *" && ret_type.c_type != "const Eina_Accessor *" | ||
1459 | ) | ||
1460 | { | ||
1461 | if ((ret_type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own)) | ||
1462 | && !as_generator("_ret_var.OwnContent = false; ") | ||
1463 | .generate(sink, attributes::unused, context)) | ||
1464 | return false; | ||
1465 | } | ||
1466 | |||
1467 | return as_generator("return _ret_var.Handle;") | 1450 | return as_generator("return _ret_var.Handle;") |
1468 | .generate(sink, attributes::unused, context); | 1451 | .generate(sink, attributes::unused, context); |
1469 | } | 1452 | } |
1470 | else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *") | 1453 | else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *") |
1471 | { | 1454 | { |
1472 | return as_generator("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var);") | 1455 | return as_generator(lit("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") |
1473 | .generate(sink, attributes::unused, context); | 1456 | .generate(sink, attributes::unused, context); |
1474 | } | 1457 | } |
1475 | else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *") | 1458 | else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *") |
1476 | { | 1459 | { |
1477 | return as_generator("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var);") | 1460 | return as_generator(lit("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") |
1478 | .generate(sink, attributes::unused, context); | 1461 | .generate(sink, attributes::unused, context); |
1479 | } | 1462 | } |
1480 | else if (ret_type.c_type != "void") | 1463 | else if (ret_type.c_type != "void") |
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index 1267a8d38c..7a3019ec45 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh | |||
@@ -72,7 +72,7 @@ struct to_internal_field_convert_generator | |||
72 | else if ((complex && (complex->outer.base_type == "iterator"))) | 72 | else if ((complex && (complex->outer.base_type == "iterator"))) |
73 | { | 73 | { |
74 | if (!as_generator( | 74 | if (!as_generator( |
75 | indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IEnumerableToIterator(_external_struct." << string << ");\n") | 75 | indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IEnumerableToIterator(_external_struct." << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") |
76 | .generate(sink, std::make_tuple(field_name, field_name), context)) | 76 | .generate(sink, std::make_tuple(field_name, field_name), context)) |
77 | return false; | 77 | return false; |
78 | } | 78 | } |
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index 32ed323113..8ba8c964bd 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs | |||
@@ -774,21 +774,37 @@ public static class Globals | |||
774 | } | 774 | } |
775 | } | 775 | } |
776 | 776 | ||
777 | internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> enumerable) | 777 | internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> enumerable, bool isMoved) |
778 | { | 778 | { |
779 | if (enumerable == null) | 779 | if (enumerable == null) |
780 | { | ||
780 | throw new ArgumentException("enumerable is null", nameof(enumerable)); | 781 | throw new ArgumentException("enumerable is null", nameof(enumerable)); |
781 | IntPtr[] intPtrs = new IntPtr[enumerable.Count()]; | 782 | } |
782 | 783 | ||
783 | int i = 0; | 784 | // If we are a wrapper around an existing Eina.Accessor, we can just forward |
785 | // it and avoid unnecessary copying in non-owning transfers. | ||
786 | var wrappedAccessor = enumerable as Eina.Accessor<T>; | ||
787 | |||
788 | if (wrappedAccessor != null && !isMoved) | ||
789 | { | ||
790 | return wrappedAccessor.Handle; | ||
791 | } | ||
792 | |||
793 | var list = new List<IntPtr>(); | ||
784 | foreach (T data in enumerable) | 794 | foreach (T data in enumerable) |
785 | { | 795 | { |
786 | intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data); | 796 | list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data)); |
787 | i++; | ||
788 | } | 797 | } |
789 | IntPtr[] dataArray = intPtrs.ToArray(); | 798 | IntPtr[] dataArray = list.ToArray(); |
790 | GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free. | 799 | GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free. |
791 | return Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length); | 800 | IntPtr ret = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length); |
801 | |||
802 | if (!isMoved) | ||
803 | { | ||
804 | // FIXME Need to free ret and unpin pinnedArray in the future. | ||
805 | } | ||
806 | |||
807 | return ret; | ||
792 | } | 808 | } |
793 | 809 | ||
794 | internal static IEnumerable<T> IteratorToIEnumerable<T>(IntPtr iterator) | 810 | internal static IEnumerable<T> IteratorToIEnumerable<T>(IntPtr iterator) |
@@ -802,22 +818,38 @@ public static class Globals | |||
802 | } | 818 | } |
803 | } | 819 | } |
804 | 820 | ||
805 | internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable) | 821 | internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable, bool isMoved) |
806 | { | 822 | { |
807 | if (enumerable == null) | 823 | if (enumerable == null) |
824 | { | ||
808 | throw new ArgumentException("enumerable is null", nameof(enumerable)); | 825 | throw new ArgumentException("enumerable is null", nameof(enumerable)); |
826 | } | ||
809 | 827 | ||
810 | var list = new List<IntPtr>(); | 828 | // If we are a wrapper around an existing Eina.Iterator, we can just forward |
811 | //IntPtr[] intPtrs = new IntPtr[enumerable.Count()]; | 829 | // it and avoid unnecessary copying in non-owning transfers. |
830 | var wrappedIterator = enumerable as Eina.Iterator<T>; | ||
812 | 831 | ||
832 | if (wrappedIterator != null && !isMoved) | ||
833 | { | ||
834 | return wrappedIterator.Handle; | ||
835 | } | ||
836 | |||
837 | var list = new List<IntPtr>(); | ||
813 | foreach (T data in enumerable) | 838 | foreach (T data in enumerable) |
814 | { | 839 | { |
815 | list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data)); | 840 | list.Add(Eina.TraitFunctions.ManagedToNativeAlloc<T>(data)); |
816 | } | 841 | } |
817 | 842 | ||
818 | IntPtr[] dataArray = list.ToArray(); | 843 | IntPtr[] dataArray = list.ToArray(); |
819 | GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free. | 844 | GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); |
820 | return Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length); | 845 | IntPtr ret = Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length); |
846 | |||
847 | if (!isMoved) | ||
848 | { | ||
849 | // FIXME Need to free ret and unpin pinnedArray in the future. | ||
850 | } | ||
851 | |||
852 | return ret; | ||
821 | } | 853 | } |
822 | 854 | ||
823 | internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list) | 855 | internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list) |
@@ -841,8 +873,9 @@ public static class Globals | |||
841 | IntPtr list = IntPtr.Zero; | 873 | IntPtr list = IntPtr.Zero; |
842 | foreach (T data in enumerable) | 874 | foreach (T data in enumerable) |
843 | { | 875 | { |
844 | list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free | 876 | list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); |
845 | } | 877 | } |
878 | // FIXME need to free `list` if the returned list is not @moved | ||
846 | return list; | 879 | return list; |
847 | } | 880 | } |
848 | 881 | ||
diff --git a/src/tests/efl_mono/Eina.cs b/src/tests/efl_mono/Eina.cs index e3c9159a33..46d89e4c55 100644 --- a/src/tests/efl_mono/Eina.cs +++ b/src/tests/efl_mono/Eina.cs | |||
@@ -4100,10 +4100,10 @@ class TestEinaIterator | |||
4100 | Test.Assert(arr.Own); | 4100 | Test.Assert(arr.Own); |
4101 | Test.Assert(arr.OwnContent); | 4101 | Test.Assert(arr.OwnContent); |
4102 | 4102 | ||
4103 | // Will take ownership of the Iterator | 4103 | // Will copy the Iterator, owning the copy. |
4104 | Test.Assert(t.EinaIteratorIntInOwn(itr)); | 4104 | Test.Assert(t.EinaIteratorIntInOwn(itr)); |
4105 | 4105 | ||
4106 | Test.Assert(!itr.Own); | 4106 | Test.Assert(itr.Own); |
4107 | Test.Assert(arr.Own); | 4107 | Test.Assert(arr.Own); |
4108 | // Content must continue to be owned by the array | 4108 | // Content must continue to be owned by the array |
4109 | Test.Assert(arr.OwnContent); | 4109 | Test.Assert(arr.OwnContent); |
@@ -4224,7 +4224,7 @@ class TestEinaIterator | |||
4224 | 4224 | ||
4225 | Test.Assert(t.EinaIteratorStrInOwn(itr)); | 4225 | Test.Assert(t.EinaIteratorStrInOwn(itr)); |
4226 | 4226 | ||
4227 | Test.Assert(!itr.Own); | 4227 | Test.Assert(itr.Own); |
4228 | Test.Assert(arr.Own); | 4228 | Test.Assert(arr.Own); |
4229 | Test.Assert(arr.OwnContent); | 4229 | Test.Assert(arr.OwnContent); |
4230 | 4230 | ||
@@ -4344,7 +4344,8 @@ class TestEinaIterator | |||
4344 | 4344 | ||
4345 | Test.Assert(t.EinaIteratorStrshareInOwn(itr)); | 4345 | Test.Assert(t.EinaIteratorStrshareInOwn(itr)); |
4346 | 4346 | ||
4347 | Test.Assert(!itr.Own); | 4347 | // Moving collections currently copy them, should not reflect on managed objects. |
4348 | Test.Assert(itr.Own); | ||
4348 | Test.Assert(arr.Own); | 4349 | Test.Assert(arr.Own); |
4349 | Test.Assert(arr.OwnContent); | 4350 | Test.Assert(arr.OwnContent); |
4350 | 4351 | ||
@@ -4464,7 +4465,7 @@ class TestEinaIterator | |||
4464 | 4465 | ||
4465 | Test.Assert(t.EinaIteratorObjInOwn(itr)); | 4466 | Test.Assert(t.EinaIteratorObjInOwn(itr)); |
4466 | 4467 | ||
4467 | Test.Assert(!itr.Own); | 4468 | Test.Assert(itr.Own); |
4468 | Test.Assert(arr.Own); | 4469 | Test.Assert(arr.Own); |
4469 | Test.Assert(arr.OwnContent); | 4470 | Test.Assert(arr.OwnContent); |
4470 | 4471 | ||
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index e946f6cf37..586a18cba3 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs | |||
@@ -257,24 +257,46 @@ class TestVariables | |||
257 | 257 | ||
258 | class TestEoAccessors | 258 | class TestEoAccessors |
259 | { | 259 | { |
260 | public static void basic_eo_accessors() | 260 | private static void do_eo_accessors(IEnumerable<int> accessor) |
261 | { | 261 | { |
262 | var obj = new Dummy.TestObject(); | 262 | var obj = new Dummy.TestObject(); |
263 | |||
264 | IEnumerable<int> acc = obj.CloneAccessor(accessor); | ||
265 | |||
266 | var zipped = acc.Zip(accessor, (first, second) => new Tuple<int, int>(first, second)); | ||
267 | |||
268 | foreach (Tuple<int, int> pair in zipped) | ||
269 | { | ||
270 | Test.AssertEquals(pair.Item1, pair.Item2); | ||
271 | } | ||
272 | obj.Dispose(); | ||
273 | } | ||
274 | |||
275 | public static void eina_eo_accessors() | ||
276 | { | ||
263 | Eina.List<int> lst = new Eina.List<int>(); | 277 | Eina.List<int> lst = new Eina.List<int>(); |
264 | lst.Append(4); | 278 | lst.Append(4); |
265 | lst.Append(3); | 279 | lst.Append(3); |
266 | lst.Append(2); | 280 | lst.Append(2); |
267 | lst.Append(5); | 281 | lst.Append(5); |
268 | IEnumerable<int> acc = obj.CloneAccessor(lst.GetAccessor()); | ||
269 | 282 | ||
270 | var zipped = acc.Zip(lst, (first, second) => new Tuple<int, int>(first, second)); | 283 | // FIXME: Replace the first accessor with the list once Eina.List implements Eina.IList |
284 | do_eo_accessors(lst.GetAccessor()); | ||
271 | 285 | ||
272 | foreach (Tuple<int, int> pair in zipped) | ||
273 | { | ||
274 | Test.AssertEquals(pair.Item1, pair.Item2); | ||
275 | } | ||
276 | lst.Dispose(); | 286 | lst.Dispose(); |
277 | obj.Dispose(); | 287 | } |
288 | |||
289 | public static void managed_eo_accessors() | ||
290 | { | ||
291 | var obj = new Dummy.TestObject(); | ||
292 | |||
293 | List<int> lst = new List<int>(); | ||
294 | lst.Add(-1); | ||
295 | lst.Add(1); | ||
296 | lst.Add(4); | ||
297 | lst.Add(42); | ||
298 | |||
299 | do_eo_accessors(lst); | ||
278 | } | 300 | } |
279 | } | 301 | } |
280 | 302 | ||