Reduce usage of Type (#323)

Replace parts of marshaller responsible for lists/arrays with
AOT-friendly logic. Use generics where possible
This commit is contained in:
Andrii Kurdiumov 2022-01-27 02:15:18 +06:00 committed by GitHub
parent c362ad1468
commit b9826da789
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 4 deletions

View file

@ -313,6 +313,21 @@ namespace GLib {
return result; return result;
} }
public static byte[] ArrayPtrToArray<TElement> (IntPtr array_ptr, int length, bool owned)
{
byte[] result = null;
if (typeof(TElement) == typeof (byte)) {
byte[] ret = new byte [length];
Marshal.Copy (array_ptr, ret, 0, length);
result = ret;
} else {
throw new InvalidOperationException ("Marshaling of " + typeof(TElement) + " arrays is not supported");
}
if (owned)
Free (array_ptr);
return result;
}
public static Array ListPtrToArray (IntPtr list_ptr, Type list_type, bool owned, bool elements_owned, Type elem_type) public static Array ListPtrToArray (IntPtr list_ptr, Type list_type, bool owned, bool elements_owned, Type elem_type)
{ {
Type array_type = elem_type == typeof (ListBase.FilenameString) ? typeof (string) : elem_type; Type array_type = elem_type == typeof (ListBase.FilenameString) ? typeof (string) : elem_type;
@ -326,6 +341,18 @@ namespace GLib {
return ListToArray (list, array_type); return ListToArray (list, array_type);
} }
public static TElement[] ListPtrToArray<TElement, TListElement> (IntPtr list_ptr, bool owned, bool elements_owned)
{
using (GLib.List list = new GLib.List (list_ptr, typeof(TListElement), owned, elements_owned))
return ListToArray<TElement> (list);
}
public static TElement[] SListPtrToArray<TElement, TListElement> (IntPtr list_ptr, bool owned, bool elements_owned)
{
using (GLib.SList list = new GLib.SList (list_ptr, typeof(TListElement), owned, elements_owned))
return ListToArray<TElement> (list);
}
public static Array PtrArrayToArray (IntPtr list_ptr, bool owned, bool elements_owned, Type elem_type) public static Array PtrArrayToArray (IntPtr list_ptr, bool owned, bool elements_owned, Type elem_type)
{ {
GLib.PtrArray array = new GLib.PtrArray (list_ptr, elem_type, owned, elements_owned); GLib.PtrArray array = new GLib.PtrArray (list_ptr, elem_type, owned, elements_owned);
@ -335,6 +362,15 @@ namespace GLib {
return ret; return ret;
} }
public static TElement[] PtrArrayToArray<TElement> (IntPtr list_ptr, bool owned, bool elements_owned)
{
GLib.PtrArray array = new GLib.PtrArray (list_ptr, typeof(TElement), owned, elements_owned);
TElement[] ret = new TElement[array.Count];
array.CopyTo (ret, 0);
array.Dispose ();
return ret;
}
public static Array ListToArray (ListBase list, System.Type type) public static Array ListToArray (ListBase list, System.Type type)
{ {
Array result = Array.CreateInstance (type, list.Count); Array result = Array.CreateInstance (type, list.Count);
@ -347,6 +383,18 @@ namespace GLib {
return result; return result;
} }
public static TElement[] ListToArray<TElement> (ListBase list)
{
TElement[] result = new TElement[list.Count];
if (list.Count > 0)
list.CopyTo (result, 0);
if (typeof(TElement).IsSubclassOf (typeof (GLib.Opaque)))
list.elements_owned = false;
return result;
}
public static T[] StructArrayFromNullTerminatedIntPtr<T> (IntPtr array) public static T[] StructArrayFromNullTerminatedIntPtr<T> (IntPtr array)
{ {
var res = new List<T> (); var res = new List<T> ();

View file

@ -35,7 +35,7 @@ namespace Gtk {
return new TreePath [0]; return new TreePath [0];
GLib.List list = new GLib.List (list_ptr, typeof (Gtk.TreePath)); GLib.List list = new GLib.List (list_ptr, typeof (Gtk.TreePath));
return (TreePath[]) GLib.Marshaller.ListToArray (list, typeof (Gtk.TreePath)); return GLib.Marshaller.ListToArray<TreePath> (list);
} }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate bool d_gtk_tree_selection_get_selected2(IntPtr raw, IntPtr model, out Gtk.TreeIter iter); delegate bool d_gtk_tree_selection_get_selected2(IntPtr raw, IntPtr model, out Gtk.TreeIter iter);

View file

@ -147,15 +147,22 @@ namespace GtkSharp.Generation {
if (ElementType != String.Empty) { if (ElementType != String.Empty) {
string args = (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false"); string args = (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false");
if (IGen.QualifiedName == "GLib.PtrArray") if (IGen.QualifiedName == "GLib.PtrArray")
return String.Format ("({0}[]) GLib.Marshaller.PtrArrayToArray ({1}, {2}, typeof({0}))", ElementType, var, args); return String.Format ("GLib.Marshaller.PtrArrayToArray<{0}> ({1}, {2})", ElementType, var, args);
else if (IGen.QualifiedName == "GLib.List")
return String.Format ("GLib.Marshaller.ListPtrToArray<{0}, {1}> ({2}, {3})", ElementType, element_ctype == "gfilename*" ? "GLib.ListBase.FilenameString" : ElementType, var, args);
else if (IGen.QualifiedName == "GLib.SList" || IGen.QualifiedName == "System.IntPtr")
return String.Format ("GLib.Marshaller.SListPtrToArray<{0}, {1}> ({2}, {3})", ElementType, element_ctype == "gfilename*" ? "GLib.ListBase.FilenameString" : ElementType, var, args);
else else
return String.Format ("({0}[]) GLib.Marshaller.ListPtrToArray ({1}, typeof({2}), {3}, typeof({4}))", ElementType, var, IGen.QualifiedName, args, element_ctype == "gfilename*" ? "GLib.ListBase.FilenameString" : ElementType); throw new InvalidOperationException($"Unsupported element marshalling configuration for element type {IGen.QualifiedName}");
} else if (IGen is IOwnable) } else if (IGen is IOwnable)
return ((IOwnable)IGen).FromNative (var, owned); return ((IOwnable)IGen).FromNative (var, owned);
else if (is_null_term) else if (is_null_term)
return String.Format ("GLib.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false"); return String.Format ("GLib.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false");
else if (is_array) else if (is_array)
return String.Format ("({0}) GLib.Marshaller.ArrayPtrToArray ({1}, typeof ({2}), (int){3}native_{4}, true)", CSType, var, IGen.QualifiedName, CountParameter.CSType == "int" ? String.Empty : "(" + CountParameter.CSType + ")", CountParameter.Name); if (CSType == "byte[]" && IGen.QualifiedName == "byte")
return String.Format ("GLib.Marshaller.ArrayPtrToArray<{0}> ({1}, (int){2}native_{3}, true)", CSType, var, CountParameter.CSType == "int" ? String.Empty : "(" + CountParameter.CSType + ")", CountParameter.Name);
else
throw new InvalidOperationException($"Unsupported array marshalling configuration for types {IGen.QualifiedName} and {CSType}");
else else
return IGen.FromNative (var); return IGen.FromNative (var);
} }