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;
}
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"));

View file

@ -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) {

View file

@ -140,10 +140,13 @@ 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)
{

View file

@ -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,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;
if (next != null || next.Name == "parameter") {
Parameter a = new Parameter (next);
@ -672,6 +688,7 @@ namespace GtkSharp.Generation {
i++;
}
}
}
} else if (p.CType == "GError**")
p = new ErrorParameter (parm);
else if (gen is StructBase || gen is ByRefGen) {

View file

@ -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);

View file

@ -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;

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='GetPath']/return-type" name="owned">true</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='GtkTreeModelFilterModifyFunc']/parameters/parameter[@name='value']" name="pass_as">ref</attr>
<attr path="/api/namespace/callback[@cname='GtkModuleDisplayInitFunc']" name="hidden">1</attr>