summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYeongjong Lee <yj34.lee@samsung.com>2019-12-16 11:24:51 -0300
committerLauro Moura <lauromoura@expertisesolutions.com.br>2019-12-16 16:56:13 -0300
commitd2f849a7a4dcfceefe4413f3e82c05355c706664 (patch)
tree6ea9177598138eedbd0e22326e6d86bc5d3aff80
parentfd40e5daa940c6952bb3eaaec2e279b078499375 (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: lauromoura 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.hh29
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh2
-rw-r--r--src/bindings/mono/eo_mono/iwrapper.cs59
-rw-r--r--src/tests/efl_mono/Eina.cs11
-rw-r--r--src/tests/efl_mono/Eo.cs38
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 8d316181c5..e761935892 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
258class TestEoAccessors 258class 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