forked from enlightenment/efl
csharp: Move collection conversions to a new file
This commit is contained in:
parent
3cbe4d3e7c
commit
786bb1fe3b
|
@ -132,9 +132,9 @@ struct unpack_event_args_visitor
|
|||
bool operator()(attributes::complex_type_def const& types) const
|
||||
{
|
||||
if (types.outer.base_type == "iterator")
|
||||
return as_generator("Efl.Eo.Globals.IteratorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
|
||||
return as_generator("Efl.Eo.CollectionConversions.IteratorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
|
||||
else if (types.outer.base_type == "accessor")
|
||||
return as_generator("Efl.Eo.Globals.AccessorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
|
||||
return as_generator("Efl.Eo.CollectionConversions.AccessorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
|
||||
else
|
||||
return as_generator("new " << eolian_mono::type << "(info, false, false)").generate(sink, type, *context);
|
||||
}
|
||||
|
|
|
@ -645,7 +645,7 @@ struct native_convert_in_variable_generator
|
|||
if (!complex)
|
||||
return false;
|
||||
return as_generator(
|
||||
"var " << string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << escape_keyword(param.param_name)
|
||||
"var " << string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(" << escape_keyword(param.param_name)
|
||||
<< ");\n"
|
||||
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
|
||||
}
|
||||
|
@ -655,7 +655,7 @@ struct native_convert_in_variable_generator
|
|||
if (!complex)
|
||||
return false;
|
||||
return as_generator(
|
||||
"var " << string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
|
||||
"var " << string << " = Efl.Eo.CollectionConversions.AccessorTo" << type << "(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
|
||||
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
|
||||
}
|
||||
else if (param.type.c_type == "Eina_Value")
|
||||
|
@ -758,7 +758,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.CollectionConversions.IEnumerableToIterator(" << escape_keyword(param.param_name) << ");\n"
|
||||
).generate(sink, var_name, context))
|
||||
return false;
|
||||
}
|
||||
|
@ -769,7 +769,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) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
|
||||
"var " << string << " = Efl.Eo.CollectionConversions.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
|
||||
).generate(sink, var_name, context))
|
||||
return false;
|
||||
}
|
||||
|
@ -1021,7 +1021,7 @@ struct convert_out_assign_generator
|
|||
if (!complex)
|
||||
return false;
|
||||
return as_generator(
|
||||
string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
|
||||
string << " = Efl.Eo.CollectionConversions.AccessorTo" << type << "(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
|
||||
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
|
||||
}
|
||||
else if (param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
|
||||
|
@ -1034,7 +1034,7 @@ struct convert_out_assign_generator
|
|||
if (!complex)
|
||||
return false;
|
||||
return as_generator(
|
||||
string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << string
|
||||
string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(" << string
|
||||
<< ");\n"
|
||||
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
|
||||
}
|
||||
|
@ -1154,7 +1154,7 @@ struct convert_return_generator
|
|||
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
|
||||
if (!complex)
|
||||
return false;
|
||||
if (!as_generator("return Efl.Eo.Globals.AccessorTo" << type << "(_ret_var, " << (ret_type.has_own ? "true" : "false") << ");")
|
||||
if (!as_generator("return Efl.Eo.CollectionConversions.AccessorTo" << type << "(_ret_var, " << (ret_type.has_own ? "true" : "false") << ");")
|
||||
.generate(sink, ret_type, context))
|
||||
return false;
|
||||
}
|
||||
|
@ -1163,7 +1163,7 @@ struct convert_return_generator
|
|||
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
|
||||
if (!complex)
|
||||
return false;
|
||||
if (!as_generator("return Efl.Eo.Globals.IteratorTo" << type << "(_ret_var);")
|
||||
if (!as_generator("return Efl.Eo.CollectionConversions.IteratorTo" << type << "(_ret_var);")
|
||||
.generate(sink, ret_type, context))
|
||||
return false;
|
||||
}
|
||||
|
@ -1312,7 +1312,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 << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
|
||||
string << " = Efl.Eo.CollectionConversions.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
|
||||
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
|
||||
return false;
|
||||
}
|
||||
|
@ -1327,7 +1327,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.CollectionConversions.IEnumerableToIterator(" << string << ");\n"
|
||||
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
|
||||
return false;
|
||||
}
|
||||
|
@ -1467,12 +1467,12 @@ struct native_convert_return_generator
|
|||
}
|
||||
else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
|
||||
{
|
||||
return as_generator(lit("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");")
|
||||
return as_generator(lit("return Efl.Eo.CollectionConversions.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("return Efl.Eo.CollectionConversions.IEnumerableToIterator(_ret_var);")
|
||||
.generate(sink, attributes::unused, context);
|
||||
}
|
||||
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")))
|
||||
{
|
||||
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.CollectionConversions.IEnumerableToIterator(_external_struct." << string << ");\n")
|
||||
.generate(sink, std::make_tuple(field_name, field_name), context))
|
||||
return false;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ struct to_external_field_convert_generator
|
|||
else if (complex && complex->outer.base_type == "iterator")
|
||||
{
|
||||
if (!as_generator(
|
||||
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.IteratorTo" << type << "(_internal_struct." << string << ");\n")
|
||||
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(_internal_struct." << string << ");\n")
|
||||
.generate(sink, std::make_tuple(field_name, field.type, field_name), context))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright 2019 by its authors. See AUTHORS.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma warning disable 1591
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Efl
|
||||
{
|
||||
namespace Eo
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class with method to convert between managed and native collections
|
||||
/// </summary>
|
||||
internal class CollectionConversions
|
||||
{
|
||||
|
||||
internal static IEnumerable<T> AccessorToIEnumerable<T>(IntPtr accessor, bool isMoved)
|
||||
{
|
||||
if (accessor == IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentException("accessor is null", nameof(accessor));
|
||||
}
|
||||
|
||||
IntPtr data = IntPtr.Zero;
|
||||
uint position = 0;
|
||||
|
||||
while (Eina.AccessorNativeFunctions.eina_accessor_data_get(accessor, position, out data))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(data);
|
||||
position += 1;
|
||||
}
|
||||
|
||||
if (isMoved)
|
||||
{
|
||||
Eina.AccessorNativeFunctions.eina_accessor_free(accessor);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToAccessor<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.Accessor, we can just forward
|
||||
// it and avoid unnecessary copying.
|
||||
var wrappedAccessor = enumerable as Eina.Accessor<T>;
|
||||
|
||||
if (wrappedAccessor != null)
|
||||
{
|
||||
if (isMoved)
|
||||
{
|
||||
wrappedAccessor.Own = false;
|
||||
}
|
||||
return wrappedAccessor.Handle;
|
||||
}
|
||||
|
||||
// TODO: Check if we're either an Eina.List or Eina.Collection?
|
||||
// We could just rewrap their native accessors
|
||||
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
|
||||
|
||||
int i = 0;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
|
||||
i++;
|
||||
}
|
||||
IntPtr[] dataArray = intPtrs.ToArray();
|
||||
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned);
|
||||
|
||||
IntPtr nativeAccessor = IntPtr.Zero;
|
||||
|
||||
if (isMoved)
|
||||
{
|
||||
// We need a custom accessor that would unpin the data when freed.
|
||||
nativeAccessor = Eina.AccessorNativeFunctions.eina_mono_owned_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(),
|
||||
(uint)IntPtr.Size,
|
||||
(uint)dataArray.Length,
|
||||
Efl.Eo.Globals.free_gchandle,
|
||||
GCHandle.ToIntPtr(pinnedArray));
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Leaking....
|
||||
nativeAccessor = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
|
||||
}
|
||||
|
||||
if (nativeAccessor == IntPtr.Zero)
|
||||
{
|
||||
pinnedArray.Free();
|
||||
throw new InvalidOperationException("Failed to get native accessor for the given container");
|
||||
}
|
||||
|
||||
return nativeAccessor;
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> IteratorToIEnumerable<T>(IntPtr iterator)
|
||||
{
|
||||
if (iterator == IntPtr.Zero)
|
||||
throw new ArgumentException("iterator is null", nameof(iterator));
|
||||
|
||||
while (Eina.IteratorNativeFunctions.eina_iterator_next(iterator, out IntPtr data))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(data);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
if (enumerable == null)
|
||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
||||
|
||||
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
|
||||
|
||||
int i = 0;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
|
||||
i++;
|
||||
}
|
||||
|
||||
IntPtr[] dataArray = intPtrs.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);
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
|
||||
{
|
||||
if (list == IntPtr.Zero)
|
||||
throw new ArgumentException("list is null", nameof(list));
|
||||
|
||||
IntPtr l;
|
||||
|
||||
for (l = list; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l));
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToList<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
if (enumerable == null)
|
||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
||||
|
||||
IntPtr list = IntPtr.Zero;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -758,145 +758,6 @@ public static class Globals
|
|||
}
|
||||
Monitor.Exit(Efl.All.InitLock);
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> AccessorToIEnumerable<T>(IntPtr accessor, bool isMoved)
|
||||
{
|
||||
if (accessor == IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentException("accessor is null", nameof(accessor));
|
||||
}
|
||||
|
||||
IntPtr data = IntPtr.Zero;
|
||||
uint position = 0;
|
||||
|
||||
while (Eina.AccessorNativeFunctions.eina_accessor_data_get(accessor, position, out data))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(data);
|
||||
position += 1;
|
||||
}
|
||||
|
||||
if (isMoved)
|
||||
{
|
||||
Eina.AccessorNativeFunctions.eina_accessor_free(accessor);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToAccessor<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.Accessor, we can just forward
|
||||
// it and avoid unnecessary copying.
|
||||
var wrappedAccessor = enumerable as Eina.Accessor<T>;
|
||||
|
||||
if (wrappedAccessor != null)
|
||||
{
|
||||
if (isMoved)
|
||||
{
|
||||
wrappedAccessor.Own = false;
|
||||
}
|
||||
return wrappedAccessor.Handle;
|
||||
}
|
||||
|
||||
// TODO: Check if we're either an Eina.List or Eina.Collection?
|
||||
// We could just rewrap their native accessors
|
||||
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
|
||||
|
||||
int i = 0;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
|
||||
i++;
|
||||
}
|
||||
IntPtr[] dataArray = intPtrs.ToArray();
|
||||
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned);
|
||||
|
||||
IntPtr nativeAccessor = IntPtr.Zero;
|
||||
|
||||
if (isMoved)
|
||||
{
|
||||
// We need a custom accessor that would unpin the data when freed.
|
||||
nativeAccessor = Eina.AccessorNativeFunctions.eina_mono_owned_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(),
|
||||
(uint)IntPtr.Size,
|
||||
(uint)dataArray.Length,
|
||||
free_gchandle,
|
||||
GCHandle.ToIntPtr(pinnedArray));
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Leaking....
|
||||
nativeAccessor = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
|
||||
}
|
||||
|
||||
if (nativeAccessor == IntPtr.Zero)
|
||||
{
|
||||
pinnedArray.Free();
|
||||
throw new InvalidOperationException("Failed to get native accessor for the given container");
|
||||
}
|
||||
|
||||
return nativeAccessor;
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> IteratorToIEnumerable<T>(IntPtr iterator)
|
||||
{
|
||||
if (iterator == IntPtr.Zero)
|
||||
throw new ArgumentException("iterator is null", nameof(iterator));
|
||||
|
||||
while (Eina.IteratorNativeFunctions.eina_iterator_next(iterator, out IntPtr data))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(data);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
if (enumerable == null)
|
||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
||||
|
||||
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
|
||||
|
||||
int i = 0;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
|
||||
i++;
|
||||
}
|
||||
|
||||
IntPtr[] dataArray = intPtrs.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);
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
|
||||
{
|
||||
if (list == IntPtr.Zero)
|
||||
throw new ArgumentException("list is null", nameof(list));
|
||||
|
||||
IntPtr l;
|
||||
|
||||
for (l = list; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l))
|
||||
{
|
||||
yield return Eina.TraitFunctions.NativeToManaged<T>(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l));
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr IEnumerableToList<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
if (enumerable == null)
|
||||
throw new ArgumentException("enumerable is null", nameof(enumerable));
|
||||
|
||||
IntPtr list = IntPtr.Zero;
|
||||
foreach (T data in enumerable)
|
||||
{
|
||||
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
} // Globals
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mono_files += files(
|
||||
'iwrapper.cs',
|
||||
'workaround.cs',
|
||||
'CollectionConversions.cs',
|
||||
'FunctionWrapper.cs',
|
||||
'NativeModule.cs',
|
||||
'EoWrapper.cs',
|
||||
|
|
Loading…
Reference in New Issue