diff --git a/generator/CallbackGen.cs b/generator/CallbackGen.cs
index 40f25c426..fde76684c 100644
--- a/generator/CallbackGen.cs
+++ b/generator/CallbackGen.cs
@@ -54,6 +54,9 @@ namespace GtkSharp.Generation {
valid = false;
}
+ if (!String.IsNullOrEmpty (retval.CountParameterName))
+ retval.CountParameter = parms.GetCountParameter (retval.CountParameterName);
+
return valid;
}
@@ -218,6 +221,9 @@ namespace GtkSharp.Generation {
if (finish.Length > 0)
sw.WriteLine (finish);
sw.WriteLine ("\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();");
+ Parameter cnt = retval.CountParameter;
+ if (cnt != null)
+ sw.WriteLine ("\t\t\t\t{0} = {1}{2};", cnt.Name, cnt.CSType == "int" ? String.Empty : "(" + cnt.MarshalType + ")(" + cnt.CSType + ")", "__ret.Length");
if (retval.CSType != "void")
sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret"));
diff --git a/generator/ManagedCallString.cs b/generator/ManagedCallString.cs
index f4387449e..31021847c 100644
--- a/generator/ManagedCallString.cs
+++ b/generator/ManagedCallString.cs
@@ -43,7 +43,7 @@ namespace GtkSharp.Generation {
user_data_param = parms[i+1].Name;
destroy_param = parms[i+2].Name;
i += 2;
- } else if (p.IsUserData && parms.IsHidden (p)) {
+ } else if ((p.IsCount || p.IsUserData) && parms.IsHidden (p)) {
user_data_param = p.Name;
continue;
} else if (p is ErrorParameter) {
diff --git a/generator/MethodBody.cs b/generator/MethodBody.cs
index 31ed62d5f..8e6665772 100644
--- a/generator/MethodBody.cs
+++ b/generator/MethodBody.cs
@@ -140,9 +140,12 @@ namespace GtkSharp.Generation {
public void Finish (StreamWriter sw, string indent)
{
- foreach (Parameter p in parameters)
+ foreach (Parameter p in parameters) {
+ if (parameters.IsHidden (p))
+ continue;
foreach (string s in p.Finish)
sw.WriteLine(indent + "\t\t\t" + s);
+ }
}
public void FinishAccessor (StreamWriter sw, Signature sig, string indent)
diff --git a/generator/Parameters.cs b/generator/Parameters.cs
index a1ba61f1e..f599d5222 100644
--- a/generator/Parameters.cs
+++ b/generator/Parameters.cs
@@ -91,8 +91,12 @@ namespace GtkSharp.Generation {
}
}
+ bool is_count;
+ bool is_count_set;
public bool IsCount {
get {
+ if (is_count_set)
+ return is_count;
if (Name.StartsWith("n_"))
switch (CSType) {
@@ -109,6 +113,10 @@ namespace GtkSharp.Generation {
else
return false;
}
+ set {
+ is_count_set = true;
+ is_count = value;
+ }
}
public bool IsDestroyNotify {
@@ -119,7 +127,6 @@ namespace GtkSharp.Generation {
public bool IsLength {
get {
-
if (Name.EndsWith("len") || Name.EndsWith("length"))
switch (CSType) {
case "int":
@@ -529,9 +536,7 @@ namespace GtkSharp.Generation {
}
public int Count {
- get {
- return param_list.Count;
- }
+ get { return param_list.Count; }
}
public int VisibleCount {
@@ -558,8 +563,7 @@ namespace GtkSharp.Generation {
if (idx > 0 && p.IsLength && p.PassAs == String.Empty && this [idx - 1].IsString)
return true;
- if (p.IsCount && ((idx > 0 && this [idx - 1].IsArray) ||
- (idx < Count - 1 && this [idx + 1].IsArray)))
+ if (p.IsCount)
return true;
if (p.CType == "GError**")
@@ -608,6 +612,16 @@ namespace GtkSharp.Generation {
set { is_static = value; }
}
+ public Parameter GetCountParameter (string param_name)
+ {
+ foreach (Parameter p in this)
+ if (p.Name == param_name) {
+ p.IsCount = true;
+ return p;
+ }
+ return null;
+ }
+
void Clear ()
{
elem = null;
@@ -663,13 +677,16 @@ namespace GtkSharp.Generation {
}
}
}
- } else if (p.IsCount && i < elem.ChildNodes.Count - 1) {
- XmlElement next = elem.ChildNodes [i + 1] as XmlElement;
- if (next != null || next.Name == "parameter") {
- Parameter a = new Parameter (next);
- if (a.IsArray) {
- p = new ArrayCountPair (next, parm, true);
- i++;
+ } else if (p.IsCount) {
+ p.IsCount = false;
+ if (i < elem.ChildNodes.Count - 1) {
+ XmlElement next = elem.ChildNodes [i + 1] as XmlElement;
+ if (next != null || next.Name == "parameter") {
+ Parameter a = new Parameter (next);
+ if (a.IsArray) {
+ p = new ArrayCountPair (next, parm, true);
+ i++;
+ }
}
}
} else if (p.CType == "GError**")
diff --git a/generator/ReturnValue.cs b/generator/ReturnValue.cs
index cf7f25308..6da64f364 100644
--- a/generator/ReturnValue.cs
+++ b/generator/ReturnValue.cs
@@ -31,15 +31,18 @@ namespace GtkSharp.Generation {
bool is_array;
bool elements_owned;
bool owned;
+ string array_length_param = String.Empty;
string ctype = String.Empty;
string default_value = String.Empty;
string element_ctype = String.Empty;
+ Parameter count_param;
public ReturnValue (XmlElement elem)
{
if (elem != null) {
is_null_term = elem.HasAttribute ("null_term_array");
- is_array = elem.HasAttribute ("array");
+ is_array = elem.HasAttribute ("array") || elem.HasAttribute ("array_length_param");
+ array_length_param = elem.GetAttribute ("array_length_param");
elements_owned = elem.GetAttribute ("elements_owned") == "true";
owned = elem.GetAttribute ("owned") == "true";
ctype = elem.GetAttribute("type");
@@ -48,6 +51,15 @@ namespace GtkSharp.Generation {
}
}
+ public Parameter CountParameter {
+ get { return count_param; }
+ set { count_param = value; }
+ }
+
+ public string CountParameterName {
+ get { return array_length_param; }
+ }
+
public string CType {
get {
return ctype;
@@ -104,9 +116,9 @@ namespace GtkSharp.Generation {
get {
if (IGen == null)
return String.Empty;
- else if (is_null_term)
+ else if (is_array || is_null_term)
return "IntPtr";
- return IGen.MarshalType + (is_array ? "[]" : String.Empty);
+ return IGen.MarshalType;
}
}
@@ -133,6 +145,8 @@ namespace GtkSharp.Generation {
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);
else
return IGen.FromNative (var);
}
@@ -147,6 +161,8 @@ namespace GtkSharp.Generation {
var = "new " + IGen.QualifiedName + "(" + var + args + ")";
} else if (is_null_term)
return String.Format ("GLib.Marshaller.StringArrayToNullTermPointer ({0})", var);
+ else if (is_array)
+ return String.Format ("GLib.Marshaller.ArrayToArrayPtr ({0})", var);
if (IGen is IManualMarshaler)
return (IGen as IManualMarshaler).AllocNative (var);
diff --git a/glib/Marshaller.cs b/glib/Marshaller.cs
index a34e82dfb..457beed45 100644
--- a/glib/Marshaller.cs
+++ b/glib/Marshaller.cs
@@ -402,6 +402,28 @@ namespace GLib {
return result;
}
+ public static IntPtr ArrayToArrayPtr (byte[] array)
+ {
+ IntPtr ret = Malloc ((ulong) array.Length);
+ Marshal.Copy (array, 0, ret, array.Length);
+ return ret;
+ }
+
+ public static Array ArrayPtrToArray (IntPtr array_ptr, Type element_type, int length, bool owned)
+ {
+ Array result = null;
+ if (element_type == typeof (byte)) {
+ byte[] ret = new byte [length];
+ Marshal.Copy (array_ptr, ret, 0, length);
+ result = ret;
+ } else {
+ throw new InvalidOperationException ("Marshaling of " + element_type + " 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;
diff --git a/gtk/Gtk.metadata b/gtk/Gtk.metadata
index 70ed8b5e6..13938e321 100644
--- a/gtk/Gtk.metadata
+++ b/gtk/Gtk.metadata
@@ -50,6 +50,7 @@
1
true
1
+ length
1
ref
1