Fix TextBufferSerializeFunc signature

* generator/CallbackGen.cs: connect return value count parameters
* generator/ManagedCallString.cs: out count params aren't special
* generator/MethodBody.cs: don't finish hidden params
* generator/Parameters.cs: explicit IsCount setting support, with
    Parameters.GetCountParameter(name) interface. Clear IsCount
    values during validation if they have no associated array. Any
    remaining count params must be associated with a retval, so
    hide them.
* generator/ReturnValue.cs: support array_length_param attribute to
    associate a return value with a "count" param.  Use new helper
    methods to marshal these array retvals to IntPtr and back.
* glib/Marshaller.cs: support for byte[] marshaling to and from
    IntPtr using a count and type in the from native direction.
* gtk/Gtk.metadata: mark TextBufferSerializeFunc return type as
    an array with the length specific in the length param.
This commit is contained in:
Mike Kestner 2011-04-28 18:38:07 -05:00
parent 2e115e2aff
commit c6a3bf4b73
7 changed files with 83 additions and 18 deletions

View file

@ -54,6 +54,9 @@ namespace GtkSharp.Generation {
valid = false; valid = false;
} }
if (!String.IsNullOrEmpty (retval.CountParameterName))
retval.CountParameter = parms.GetCountParameter (retval.CountParameterName);
return valid; return valid;
} }
@ -218,6 +221,9 @@ namespace GtkSharp.Generation {
if (finish.Length > 0) if (finish.Length > 0)
sw.WriteLine (finish); sw.WriteLine (finish);
sw.WriteLine ("\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();"); 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") if (retval.CSType != "void")
sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret")); sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret"));

View file

@ -43,7 +43,7 @@ namespace GtkSharp.Generation {
user_data_param = parms[i+1].Name; user_data_param = parms[i+1].Name;
destroy_param = parms[i+2].Name; destroy_param = parms[i+2].Name;
i += 2; i += 2;
} else if (p.IsUserData && parms.IsHidden (p)) { } else if ((p.IsCount || p.IsUserData) && parms.IsHidden (p)) {
user_data_param = p.Name; user_data_param = p.Name;
continue; continue;
} else if (p is ErrorParameter) { } else if (p is ErrorParameter) {

View file

@ -140,10 +140,13 @@ namespace GtkSharp.Generation {
public void Finish (StreamWriter sw, string indent) 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) foreach (string s in p.Finish)
sw.WriteLine(indent + "\t\t\t" + s); sw.WriteLine(indent + "\t\t\t" + s);
} }
}
public void FinishAccessor (StreamWriter sw, Signature sig, string indent) public void FinishAccessor (StreamWriter sw, Signature sig, string indent)
{ {

View file

@ -91,8 +91,12 @@ namespace GtkSharp.Generation {
} }
} }
bool is_count;
bool is_count_set;
public bool IsCount { public bool IsCount {
get { get {
if (is_count_set)
return is_count;
if (Name.StartsWith("n_")) if (Name.StartsWith("n_"))
switch (CSType) { switch (CSType) {
@ -109,6 +113,10 @@ namespace GtkSharp.Generation {
else else
return false; return false;
} }
set {
is_count_set = true;
is_count = value;
}
} }
public bool IsDestroyNotify { public bool IsDestroyNotify {
@ -119,7 +127,6 @@ namespace GtkSharp.Generation {
public bool IsLength { public bool IsLength {
get { get {
if (Name.EndsWith("len") || Name.EndsWith("length")) if (Name.EndsWith("len") || Name.EndsWith("length"))
switch (CSType) { switch (CSType) {
case "int": case "int":
@ -529,9 +536,7 @@ namespace GtkSharp.Generation {
} }
public int Count { public int Count {
get { get { return param_list.Count; }
return param_list.Count;
}
} }
public int VisibleCount { public int VisibleCount {
@ -558,8 +563,7 @@ namespace GtkSharp.Generation {
if (idx > 0 && p.IsLength && p.PassAs == String.Empty && this [idx - 1].IsString) if (idx > 0 && p.IsLength && p.PassAs == String.Empty && this [idx - 1].IsString)
return true; return true;
if (p.IsCount && ((idx > 0 && this [idx - 1].IsArray) || if (p.IsCount)
(idx < Count - 1 && this [idx + 1].IsArray)))
return true; return true;
if (p.CType == "GError**") if (p.CType == "GError**")
@ -608,6 +612,16 @@ namespace GtkSharp.Generation {
set { is_static = value; } 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 () void Clear ()
{ {
elem = null; elem = null;
@ -663,7 +677,9 @@ namespace GtkSharp.Generation {
} }
} }
} }
} else if (p.IsCount && i < elem.ChildNodes.Count - 1) { } else if (p.IsCount) {
p.IsCount = false;
if (i < elem.ChildNodes.Count - 1) {
XmlElement next = elem.ChildNodes [i + 1] as XmlElement; XmlElement next = elem.ChildNodes [i + 1] as XmlElement;
if (next != null || next.Name == "parameter") { if (next != null || next.Name == "parameter") {
Parameter a = new Parameter (next); Parameter a = new Parameter (next);
@ -672,6 +688,7 @@ namespace GtkSharp.Generation {
i++; i++;
} }
} }
}
} else if (p.CType == "GError**") } else if (p.CType == "GError**")
p = new ErrorParameter (parm); p = new ErrorParameter (parm);
else if (gen is StructBase || gen is ByRefGen) { else if (gen is StructBase || gen is ByRefGen) {

View file

@ -31,15 +31,18 @@ namespace GtkSharp.Generation {
bool is_array; bool is_array;
bool elements_owned; bool elements_owned;
bool owned; bool owned;
string array_length_param = String.Empty;
string ctype = String.Empty; string ctype = String.Empty;
string default_value = String.Empty; string default_value = String.Empty;
string element_ctype = String.Empty; string element_ctype = String.Empty;
Parameter count_param;
public ReturnValue (XmlElement elem) public ReturnValue (XmlElement elem)
{ {
if (elem != null) { if (elem != null) {
is_null_term = elem.HasAttribute ("null_term_array"); 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"; elements_owned = elem.GetAttribute ("elements_owned") == "true";
owned = elem.GetAttribute ("owned") == "true"; owned = elem.GetAttribute ("owned") == "true";
ctype = elem.GetAttribute("type"); 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 { public string CType {
get { get {
return ctype; return ctype;
@ -104,9 +116,9 @@ namespace GtkSharp.Generation {
get { get {
if (IGen == null) if (IGen == null)
return String.Empty; return String.Empty;
else if (is_null_term) else if (is_array || is_null_term)
return "IntPtr"; 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); 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)
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 else
return IGen.FromNative (var); return IGen.FromNative (var);
} }
@ -147,6 +161,8 @@ namespace GtkSharp.Generation {
var = "new " + IGen.QualifiedName + "(" + var + args + ")"; var = "new " + IGen.QualifiedName + "(" + var + args + ")";
} else if (is_null_term) } else if (is_null_term)
return String.Format ("GLib.Marshaller.StringArrayToNullTermPointer ({0})", var); return String.Format ("GLib.Marshaller.StringArrayToNullTermPointer ({0})", var);
else if (is_array)
return String.Format ("GLib.Marshaller.ArrayToArrayPtr ({0})", var);
if (IGen is IManualMarshaler) if (IGen is IManualMarshaler)
return (IGen as IManualMarshaler).AllocNative (var); return (IGen as IManualMarshaler).AllocNative (var);

View file

@ -402,6 +402,28 @@ namespace GLib {
return result; 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) 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;

View file

@ -50,6 +50,7 @@
<attr path="/api/namespace/boxed[@cname='GtkTreeRowReference']/method[@name='Free']" name="deprecated">1</attr> <attr path="/api/namespace/boxed[@cname='GtkTreeRowReference']/method[@name='Free']" name="deprecated">1</attr>
<attr path="/api/namespace/boxed[@cname='GtkTreeRowReference']/method[@name='GetPath']/return-type" name="owned">true</attr> <attr path="/api/namespace/boxed[@cname='GtkTreeRowReference']/method[@name='GetPath']/return-type" name="owned">true</attr>
<attr path="/api/namespace/callback[@cname='GtkClipboardRichTextReceivedFunc']" name="hidden">1</attr> <attr path="/api/namespace/callback[@cname='GtkClipboardRichTextReceivedFunc']" name="hidden">1</attr>
<attr path="/api/namespace/callback[@cname='GtkTextBufferSerializeFunc']/return-type" name="array_length_param">length</attr>
<attr path="/api/namespace/callback[@cname='GtkTextBufferDeserializeFunc']/*/*[@name='data']" name="array">1</attr> <attr path="/api/namespace/callback[@cname='GtkTextBufferDeserializeFunc']/*/*[@name='data']" name="array">1</attr>
<attr path="/api/namespace/callback[@cname='GtkTreeModelFilterModifyFunc']/parameters/parameter[@name='value']" name="pass_as">ref</attr> <attr path="/api/namespace/callback[@cname='GtkTreeModelFilterModifyFunc']/parameters/parameter[@name='value']" name="pass_as">ref</attr>
<attr path="/api/namespace/callback[@cname='GtkModuleDisplayInitFunc']" name="hidden">1</attr> <attr path="/api/namespace/callback[@cname='GtkModuleDisplayInitFunc']" name="hidden">1</attr>