diff --git a/Source/Libs/GLibSharp/Marshaller.cs b/Source/Libs/GLibSharp/Marshaller.cs index 23af0cd4d..449e5b7f3 100644 --- a/Source/Libs/GLibSharp/Marshaller.cs +++ b/Source/Libs/GLibSharp/Marshaller.cs @@ -313,6 +313,21 @@ namespace GLib { return result; } + public static byte[] ArrayPtrToArray (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) { Type array_type = elem_type == typeof (ListBase.FilenameString) ? typeof (string) : elem_type; @@ -326,6 +341,18 @@ namespace GLib { return ListToArray (list, array_type); } + public static TElement[] ListPtrToArray (IntPtr list_ptr, bool owned, bool elements_owned) + { + using (GLib.List list = new GLib.List (list_ptr, typeof(TListElement), owned, elements_owned)) + return ListToArray (list); + } + + public static TElement[] SListPtrToArray (IntPtr list_ptr, bool owned, bool elements_owned) + { + using (GLib.SList list = new GLib.SList (list_ptr, typeof(TListElement), owned, elements_owned)) + return ListToArray (list); + } + 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); @@ -335,6 +362,15 @@ namespace GLib { return ret; } + public static TElement[] PtrArrayToArray (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) { Array result = Array.CreateInstance (type, list.Count); @@ -347,6 +383,18 @@ namespace GLib { return result; } + public static TElement[] ListToArray (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 (IntPtr array) { var res = new List (); diff --git a/Source/Libs/GtkSharp/TreeSelection.cs b/Source/Libs/GtkSharp/TreeSelection.cs index bcf29c684..3b1adfec6 100644 --- a/Source/Libs/GtkSharp/TreeSelection.cs +++ b/Source/Libs/GtkSharp/TreeSelection.cs @@ -35,7 +35,7 @@ namespace Gtk { return new TreePath [0]; GLib.List list = new GLib.List (list_ptr, typeof (Gtk.TreePath)); - return (TreePath[]) GLib.Marshaller.ListToArray (list, typeof (Gtk.TreePath)); + return GLib.Marshaller.ListToArray (list); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool d_gtk_tree_selection_get_selected2(IntPtr raw, IntPtr model, out Gtk.TreeIter iter); diff --git a/Source/Tools/GapiCodegen/ReturnValue.cs b/Source/Tools/GapiCodegen/ReturnValue.cs index f700e668a..a38161540 100644 --- a/Source/Tools/GapiCodegen/ReturnValue.cs +++ b/Source/Tools/GapiCodegen/ReturnValue.cs @@ -147,15 +147,22 @@ namespace GtkSharp.Generation { if (ElementType != String.Empty) { string args = (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false"); 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 - 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) return ((IOwnable)IGen).FromNative (var, owned); else if (is_null_term) return String.Format ("GLib.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false"); 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 return IGen.FromNative (var); }