From 53312d5fc075af4189b65d12238c5f142415ccb4 Mon Sep 17 00:00:00 2001 From: Stephan Sundermann Date: Wed, 14 Aug 2013 13:16:40 +0200 Subject: [PATCH] generator: fixed optional array parameters --- generator/Signature.cs | 5 ++++- generator/StructField.cs | 18 +++++++++++++++++- glib/Marshaller.cs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/generator/Signature.cs b/generator/Signature.cs index c63ba75b0..c2f942ac3 100644 --- a/generator/Signature.cs +++ b/generator/Signature.cs @@ -149,7 +149,10 @@ namespace GtkSharp.Generation { result [i] = p.PassAs != "" ? p.PassAs + " " : ""; if (p.IsOptional && p.PassAs == String.Empty) { - result [i++] += p.Generatable.DefaultValue; + if (p.IsArray) + result [i++] += "null"; + else + result [i++] += p.Generatable.DefaultValue; } else result [i++] += p.Name; diff --git a/generator/StructField.cs b/generator/StructField.cs index d60273cb0..58ccf1f11 100644 --- a/generator/StructField.cs +++ b/generator/StructField.cs @@ -58,6 +58,10 @@ namespace GtkSharp.Generation { } } + bool IsNullTermArray { + get { return elem.GetAttributeAsBoolean ("null_term_array"); } + } + public new string CSType { get { string type = base.CSType; @@ -143,9 +147,21 @@ namespace GtkSharp.Generation { string wrapped_name = SymbolTable.Table.MangleName (CName); IGeneratable gen = table [CType]; - if (IsArray) { + if (IsArray && !IsNullTermArray) { sw.WriteLine (indent + "[MarshalAs (UnmanagedType.ByValArray, SizeConst=" + ArrayLength + ")]"); sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, StudlyName); + } else if (IsArray && IsNullTermArray) { + sw.WriteLine (indent + "private {0} {1};", "IntPtr", StudlyName+ "Ptr"); + if ((Readable || Writable) && Access == "public") { + sw.WriteLine (indent + "public {0} {1} {{", CSType, StudlyName); + if (Readable) + sw.WriteLine (indent + "\tget {{ return GLib.Marshaller.StructArrayFromNullTerminatedIntPtr<{0}> ({1}); }}", + base.CSType, StudlyName + "Ptr"); + if (Writable) + sw.WriteLine (indent + "\tset {{ {0} = GLib.Marshaller.StructArrayToNullTerminatedStructArrayIntPtr<{1}> (value); }}", + StudlyName + "Ptr", base.CSType); + sw.WriteLine (indent + "}"); + } } else if (IsBitfield) { base.Generate (gen_info, indent); } else if (gen is IAccessor) { diff --git a/glib/Marshaller.cs b/glib/Marshaller.cs index e08792ddb..ff38caba7 100644 --- a/glib/Marshaller.cs +++ b/glib/Marshaller.cs @@ -463,6 +463,39 @@ namespace GLib { return result; } + + public static T[] StructArrayFromNullTerminatedIntPtr (IntPtr array) + { + var res = new List (); + IntPtr current = array; + T currentStruct = default(T); + + while (current != IntPtr.Zero) { + Marshal.PtrToStructure (current, currentStruct); + res.Add (currentStruct); + current = (IntPtr) ((long)current + Marshal.SizeOf (typeof (T))); + } + + return res.ToArray (); + } + + public static IntPtr StructArrayToNullTerminatedStructArrayIntPtr (T[] InputArray) + { + int intPtrSize = Marshal.SizeOf (typeof (IntPtr)); + IntPtr mem = Marshal.AllocHGlobal ((InputArray.Length + 1) * intPtrSize); + + for (int i = 0; i < InputArray.Length; i++) { + IntPtr structPtr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (T))); + Marshal.StructureToPtr (InputArray[i], structPtr, false); + // jump to next pointer + Marshal.WriteIntPtr (mem, structPtr); + mem = (IntPtr) ((long)mem + intPtrSize); + } + // null terminate + Marshal.WriteIntPtr (mem, IntPtr.Zero); + + return mem; + } } }