* generator/ManagedCallString.cs (Setup, Finish, ToString): Add

new methods to allow arbitrary setup and teardown code around the
        managed call. When passing a type with "complicated" marshalling
        requirements as a ref or out param, first assign the value to a
        temporary variable (in Setup), then pass the temp as the ref or
        out param (in ToString), and then assign the new value back to the
        original argument (in Finish).

        * generator/Signal.cs: 
        * generator/SignalHandler.cs: Update to generate correct glue for
        signals with "ref" or "out" params. (#70566)

        * generator/VirtualMethod.cs: Update for ManagedCallString change

        * generator/IGeneratable.cs: add comments explaining what each
        member does

        * gtk/Gtk.metadata: mark Editable.InsertText's "position" arg
        * pass-by-ref

        * sample/Size.cs: connect to the SizeRequested event and override
        it, to test/demo the changes

svn path=/trunk/gtk-sharp/; revision=37854
This commit is contained in:
Dan Winship 2004-12-16 23:38:35 +00:00
parent 88cc4817f5
commit faaccd7e0b
15 changed files with 169 additions and 26 deletions

View File

@ -1,3 +1,27 @@
2004-12-16 Dan Winship <danw@novell.com>
* generator/ManagedCallString.cs (Setup, Finish, ToString): Add
new methods to allow arbitrary setup and teardown code around the
managed call. When passing a type with "complicated" marshalling
requirements as a ref or out param, first assign the value to a
temporary variable (in Setup), then pass the temp as the ref or
out param (in ToString), and then assign the new value back to the
original argument (in Finish).
* generator/Signal.cs:
* generator/SignalHandler.cs: Update to generate correct glue for
signals with "ref" or "out" params. (#70566)
* generator/VirtualMethod.cs: Update for ManagedCallString change
* generator/IGeneratable.cs: add comments explaining what each
member does
* gtk/Gtk.metadata: mark Editable.InsertText's "position" arg pass-by-ref
* sample/Size.cs: connect to the SizeRequested event and override
it, to test/demo the changes
2004-12-16 Dan Winship <danw@novell.com> 2004-12-16 Dan Winship <danw@novell.com>
* parser/gapi_pp.pl: Don't strip out /*< public >*/ and * parser/gapi_pp.pl: Don't strip out /*< public >*/ and
@ -19,8 +43,8 @@
wrapper properties for private fields, since the only code that wrapper properties for private fields, since the only code that
could use them is the generated code, which won't. could use them is the generated code, which won't.
See doc/ChangeLog for the (very minimal) fallout from these Part of #69514. See doc/ChangeLog for the (very minimal) fallout
changes. from these changes.
2004-12-16 Mike Kestner <mkestner@novell.com> 2004-12-16 Mike Kestner <mkestner@novell.com>

View File

@ -1,3 +1,17 @@
2004-12-16 Dan Winship <danw@novell.com>
* en/Gtk/InputArgs.xml (NewValue):
* en/Gtk/ToggleSizeRequestedArgs.xml (Requisition): now write-only
rather than read-only
* en/Gtk/SizeRequestedArgs.xml (Requisition):
* en/Gtk/TextInsertedArgs.xml (Position): now read-write
* en/Gtk/Entry.xml (OnTextInserted): "position" is now "ref"
rather than "out"
* en/Gtk/RowsReorderedArgs.xml (NewOrder): changed, but still broken
2004-12-16 Dan Winship <danw@novell.com> 2004-12-16 Dan Winship <danw@novell.com>
* en/Art/AlphaGamma.xml: * en/Art/AlphaGamma.xml:

View File

@ -955,14 +955,14 @@ class EntrySample
</Docs> </Docs>
</Member> </Member>
<Member MemberName="OnTextInserted"> <Member MemberName="OnTextInserted">
<MemberSignature Language="C#" Value="protected virtual void OnTextInserted (string text, out int position);" /> <MemberSignature Language="C#" Value="protected virtual void OnTextInserted (string text, ref int position);" />
<MemberType>Method</MemberType> <MemberType>Method</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>System.Void</ReturnType> <ReturnType>System.Void</ReturnType>
</ReturnValue> </ReturnValue>
<Parameters> <Parameters>
<Parameter Name="text" Type="System.String" /> <Parameter Name="text" Type="System.String" />
<Parameter Name="position" Type="System.Int32&amp;" RefType="out" /> <Parameter Name="position" Type="System.Int32&amp;" RefType="ref" />
</Parameters> </Parameters>
<Docs> <Docs>
<summary>Default handler for the <see cref="M:Gtk.Entry.TextInserted" /> event.</summary> <summary>Default handler for the <see cref="M:Gtk.Entry.TextInserted" /> event.</summary>

View File

@ -33,14 +33,14 @@
</Docs> </Docs>
</Member> </Member>
<Member MemberName="NewValue"> <Member MemberName="NewValue">
<MemberSignature Language="C#" Value="public double NewValue { get; };" /> <MemberSignature Language="C#" Value="public double NewValue { set; };" />
<MemberType>Property</MemberType> <MemberType>Property</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>System.Double</ReturnType> <ReturnType>System.Double</ReturnType>
</ReturnValue> </ReturnValue>
<Docs> <Docs>
<summary>The new value given as input.</summary> <summary>The new value</summary>
<returns>A <see cref="T:System.Double" /></returns> <returns>a <see cref="T:System.Double" /></returns>
<remarks /> <remarks />
</Docs> </Docs>
</Member> </Member>

View File

@ -52,7 +52,7 @@
</Docs> </Docs>
</Member> </Member>
<Member MemberName="NewOrder"> <Member MemberName="NewOrder">
<MemberSignature Language="C#" Value="public int NewOrder { get; };" /> <MemberSignature Language="C#" Value="public int NewOrder { set; };" />
<MemberType>Property</MemberType> <MemberType>Property</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>System.Int32</ReturnType> <ReturnType>System.Int32</ReturnType>

View File

@ -33,15 +33,25 @@
</Docs> </Docs>
</Member> </Member>
<Member MemberName="Requisition"> <Member MemberName="Requisition">
<MemberSignature Language="C#" Value="public Gtk.Requisition Requisition { get; };" /> <MemberSignature Language="C#" Value="public Gtk.Requisition Requisition { set; get; };" />
<MemberType>Property</MemberType> <MemberType>Property</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>Gtk.Requisition</ReturnType> <ReturnType>Gtk.Requisition</ReturnType>
</ReturnValue> </ReturnValue>
<Parameters />
<Docs> <Docs>
<summary>The width and height this widget would like to have.</summary> <summary>The width and height this widget would like to have.</summary>
<returns>A <see cref="T:Gtk.Requisition" /></returns> <returns>A <see cref="T:Gtk.Requisition" /></returns>
<remarks /> <remarks>
<example>
<code lang="C#">Requisition req = args.Requisition;
req.Width = 100;
req.Height = 200;
// NB: You must assign the value back to args.Requisition
args.Requisition = req;</code>
</example>
</remarks>
</Docs> </Docs>
</Member> </Member>
</Members> </Members>

View File

@ -52,13 +52,13 @@
</Docs> </Docs>
</Member> </Member>
<Member MemberName="Position"> <Member MemberName="Position">
<MemberSignature Language="C#" Value="public int Position { get; };" /> <MemberSignature Language="C#" Value="public int Position { set; get; };" />
<MemberType>Property</MemberType> <MemberType>Property</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>System.Int32</ReturnType> <ReturnType>System.Int32</ReturnType>
</ReturnValue> </ReturnValue>
<Docs> <Docs>
<summary>The position within the widget text where the text was inserted.</summary> <summary>The position at which to insert the new text. On return, it should point to the position after the inserted text.</summary>
<returns>An integer, the insert position.</returns> <returns>An integer, the insert position.</returns>
<remarks /> <remarks />
</Docs> </Docs>

View File

@ -33,14 +33,14 @@
</Docs> </Docs>
</Member> </Member>
<Member MemberName="Requisition"> <Member MemberName="Requisition">
<MemberSignature Language="C#" Value="public int Requisition { get; };" /> <MemberSignature Language="C#" Value="public int Requisition { set; };" />
<MemberType>Property</MemberType> <MemberType>Property</MemberType>
<ReturnValue> <ReturnValue>
<ReturnType>System.Int32</ReturnType> <ReturnType>System.Int32</ReturnType>
</ReturnValue> </ReturnValue>
<Docs> <Docs>
<summary>The size that was requested.</summary> <summary>The requested toggle size</summary>
<returns>A <see cref="T:System.Int32" /></returns> <returns>a <see cref="T:System.Int32" /></returns>
<remarks /> <remarks />
</Docs> </Docs>
</Member> </Member>

View File

@ -23,24 +23,37 @@ namespace GtkSharp.Generation {
public interface IGeneratable { public interface IGeneratable {
// The C name of the generatable
string CName {get;} string CName {get;}
string MarshalType {get;} // The (short) C# name of the generatable
string MarshalReturnType {get;}
string ToNativeReturnType {get;}
string Name {get;} string Name {get;}
// The fully-qualified C# name of the generatable
string QualifiedName {get;} string QualifiedName {get;}
// The type (possibly including "ref" or "out") to use in the import
// signature when passing this generatable to unmanaged code
string MarshalType {get;}
// The type to use as the return type in an import signature when
// receiving this generatable back from unmanaged code
string MarshalReturnType {get;}
// The type to use in a managed callback signature when returning this
// generatable to unmanaged code
string ToNativeReturnType {get;}
// Generates an expression to convert var_name to MarshalType
string CallByName (string var_name); string CallByName (string var_name);
// Generates an expression to convert var from MarshalType
string FromNative (string var); string FromNative (string var);
// Generates an expression to convert var from MarshalReturnType
string FromNativeReturn (string var); string FromNativeReturn (string var);
// Generates an expression to convert var to ToNativeReturnType
string ToNativeReturn (string var); string ToNativeReturn (string var);
void Generate (); void Generate ();

View File

@ -28,6 +28,7 @@ namespace GtkSharp.Generation {
public class ManagedCallString { public class ManagedCallString {
ArrayList parms = new ArrayList (); ArrayList parms = new ArrayList ();
ArrayList special = new ArrayList ();
public ManagedCallString (Parameters parms) public ManagedCallString (Parameters parms)
{ {
@ -36,9 +37,37 @@ namespace GtkSharp.Generation {
if (p.IsLength && parms [i-1].IsString) if (p.IsLength && parms [i-1].IsString)
continue; continue;
this.parms.Add (p); this.parms.Add (p);
IGeneratable igen = p.Generatable;
if ((igen is StructGen || p.PassAs != "") &&
(p.Name != igen.FromNative (p.Name)))
this.special.Add (true);
else
this.special.Add (false);
} }
} }
public string Setup (string indent)
{
string ret = "";
for (int i = 0; i < parms.Count; i ++) {
if ((bool)special[i] == false)
continue;
Parameter p = parms [i] as Parameter;
IGeneratable igen = p.Generatable;
string pass_as = igen is StructGen ? "ref" : p.PassAs;
ret += indent + igen.QualifiedName + " my" + p.Name;
if (igen is StructGen || p.PassAs == "ref")
ret += " = " + igen.FromNative (p.Name);
ret += ";\n";
}
return ret;
}
public override string ToString () public override string ToString ()
{ {
if (parms.Count < 1) if (parms.Count < 1)
@ -50,11 +79,28 @@ namespace GtkSharp.Generation {
Parameter p = parms [i] as Parameter; Parameter p = parms [i] as Parameter;
IGeneratable igen = p.Generatable; IGeneratable igen = p.Generatable;
result [i] = igen is StructGen ? "ref " : (p.PassAs == "" ? "" : p.PassAs + " "); result [i] = igen is StructGen ? "ref " : (p.PassAs == "" ? "" : p.PassAs + " ");
result [i] += igen.FromNative (p.Name); result [i] += ((bool)special[i]) ? "my" + p.Name : igen.FromNative (p.Name);
} }
return String.Join (", ", result); return String.Join (", ", result);
} }
public string Finish (string indent)
{
string ret = "";
for (int i = 0; i < parms.Count; i ++) {
if ((bool)special[i] == false)
continue;
Parameter p = parms [i] as Parameter;
IGeneratable igen = p.Generatable;
ret += indent + p.Name + " = " + igen.CallByName ("my" + p.Name) + ";\n";
}
return ret;
}
} }
} }

View File

@ -165,9 +165,16 @@ namespace GtkSharp.Generation {
if (parms != null) { if (parms != null) {
for (int i = 1; i < parms.Count; i++) { for (int i = 1; i < parms.Count; i++) {
sw.WriteLine ("\t\tpublic " + parms[i].CSType + " " + parms[i].StudlyName + "{"); sw.WriteLine ("\t\tpublic " + parms[i].CSType + " " + parms[i].StudlyName + "{");
sw.WriteLine ("\t\t\tget {"); if (parms[i].PassAs != "out") {
sw.WriteLine ("\t\t\t\treturn (" + parms[i].CSType + ") Args[" + (i - 1) + "];"); sw.WriteLine ("\t\t\tget {");
sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\t\treturn (" + parms[i].CSType + ") Args[" + (i - 1) + "];");
sw.WriteLine ("\t\t\t}");
}
if (parms[i].PassAs != "") {
sw.WriteLine ("\t\t\tset {");
sw.WriteLine ("\t\t\t\tArgs[" + (i - 1) + "] = (" + parms[i].CSType + ")value;");
sw.WriteLine ("\t\t\t}");
}
sw.WriteLine ("\t\t}"); sw.WriteLine ("\t\t}");
sw.WriteLine (); sw.WriteLine ();
} }
@ -222,8 +229,10 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + isig.ToString () + ")"); sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + isig.ToString () + ")");
sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t{0} obj = GLib.Object.GetObject ({1}, false) as {0};", implementor != null ? implementor.Name : container_type.Name, parms[0].Name); sw.WriteLine ("\t\t\t{0} obj = GLib.Object.GetObject ({1}, false) as {0};", implementor != null ? implementor.Name : container_type.Name, parms[0].Name);
sw.Write (call.Setup ("\t\t\t"));
sw.Write ("\t\t\t{0}", IsVoid ? "" : "return "); sw.Write ("\t\t\t{0}", IsVoid ? "" : "return ");
sw.WriteLine ("obj.{0} ({1});", "On" + Name, call.ToString ()); sw.WriteLine ("obj.{0} ({1});", "On" + Name, call.ToString ());
sw.Write (call.Finish ("\t\t\t"));
sw.WriteLine ("\t\t}\n"); sw.WriteLine ("\t\t}\n");
string cname = "\"" + elem.GetAttribute("cname") + "\""; string cname = "\"" + elem.GetAttribute("cname") + "\"";
sw.WriteLine ("\t\tprivate static void Override" + Name + " (GLib.GType gtype)"); sw.WriteLine ("\t\tprivate static void Override" + Name + " (GLib.GType gtype)");

View File

@ -65,8 +65,14 @@ namespace GtkSharp.Generation {
if (i > 0) if (i > 0)
result += ", "; result += ", ";
if (parms[i].PassAs != "")
result += parms[i].PassAs + " ";
result += (parms[i].MarshalType + " arg" + i); result += (parms[i].MarshalType + " arg" + i);
} }
result = result.Replace ("out ref", "out");
result = result.Replace ("ref ref", "ref");
return result; return result;
} }
} }
@ -75,6 +81,7 @@ namespace GtkSharp.Generation {
get { get {
string result = SymbolTable.Table.GetName (retval.CType); string result = SymbolTable.Table.GetName (retval.CType);
for (int i = 0; i < parms.Count; i++) { for (int i = 0; i < parms.Count; i++) {
result += parms[i].PassAs;
if (parms[i].Generatable is ObjectGen || parms[i].Generatable is InterfaceGen) { if (parms[i].Generatable is ObjectGen || parms[i].Generatable is InterfaceGen) {
result += "Object"; result += "Object";
} else { } else {
@ -140,6 +147,9 @@ namespace GtkSharp.Generation {
sw.WriteLine("\t\t\targs.Args = new object[" + (parms.Count-1) + "];"); sw.WriteLine("\t\t\targs.Args = new object[" + (parms.Count-1) + "];");
} }
for (int idx=1; idx < parms.Count; idx++) { for (int idx=1; idx < parms.Count; idx++) {
if (parms[idx].PassAs == "out")
continue;
string ctype = parms[idx].CType; string ctype = parms[idx].CType;
ClassBase wrapper = table.GetClassGen (ctype); ClassBase wrapper = table.GetClassGen (ctype);
if ((wrapper != null && !(wrapper is StructBase)) || table.IsManuallyWrapped (ctype)) { if ((wrapper != null && !(wrapper is StructBase)) || table.IsManuallyWrapped (ctype)) {
@ -159,6 +169,11 @@ namespace GtkSharp.Generation {
sw.WriteLine("\t\t\targv[0] = inst._obj;"); sw.WriteLine("\t\t\targv[0] = inst._obj;");
sw.WriteLine("\t\t\targv[1] = args;"); sw.WriteLine("\t\t\targv[1] = args;");
sw.WriteLine("\t\t\tinst._handler.DynamicInvoke(argv);"); sw.WriteLine("\t\t\tinst._handler.DynamicInvoke(argv);");
for (int idx=1; idx < parms.Count; idx++) {
if (parms[idx].PassAs != "") {
sw.WriteLine ("\t\t\targ" + idx + " = " + table.ToNativeReturn (parms[idx].CType, "((" + parms[idx].CSType + ")args.Args[" + (idx - 1) + "])") + ";");
}
}
if (retval.CSType != "void") { if (retval.CSType != "void") {
sw.WriteLine ("\t\t\tif (args.RetVal == null)"); sw.WriteLine ("\t\t\tif (args.RetVal == null)");
if (retval.CSType == "bool") if (retval.CSType == "bool")

View File

@ -81,11 +81,13 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + Name + "Callback (" + isig + ")"); sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + Name + "Callback (" + isig + ")");
sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t" + type + " __obj = GLib.Object.GetObject (" + name + ", false) as " + type + ";"); sw.WriteLine ("\t\t\t" + type + " __obj = GLib.Object.GetObject (" + name + ", false) as " + type + ";");
sw.Write (call.Setup ("\t\t\t"));
if (retval.CSType == "void") if (retval.CSType == "void")
sw.WriteLine ("\t\t\t" + call_string + ";"); sw.WriteLine ("\t\t\t" + call_string + ";");
else { else {
sw.WriteLine ("\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, call_string) + ";"); sw.WriteLine ("\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, call_string) + ";");
} }
sw.Write (call.Finish ("\t\t\t"));
sw.WriteLine ("\t\t}"); sw.WriteLine ("\t\t}");
} }

View File

@ -69,6 +69,7 @@
<attr path="/api/namespace/interface[@cname='GtkEditable']/method[@name='InsertText']/*/*[@name='position']" name="pass_as">ref</attr> <attr path="/api/namespace/interface[@cname='GtkEditable']/method[@name='InsertText']/*/*[@name='position']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/method[@name='SetEditable']" name="name">SetIsEditable</attr> <attr path="/api/namespace/interface[@cname='GtkEditable']/method[@name='SetEditable']" name="name">SetIsEditable</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='DeleteText']" name="name">TextDeleted</attr> <attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='DeleteText']" name="name">TextDeleted</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']/*/*[@name='position']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']" name="name">TextInserted</attr> <attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']" name="name">TextInserted</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetFilenames']" name="hidden">1</attr> <attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetFilenames']" name="hidden">1</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetUris']" name="hidden">1</attr> <attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetUris']" name="hidden">1</attr>

View File

@ -18,6 +18,7 @@ namespace GtkSamples {
Gtk.Window win = new Gtk.Window ("Gtk# Hello World"); Gtk.Window win = new Gtk.Window ("Gtk# Hello World");
win.DeleteEvent += new DeleteEventHandler (Window_Delete); win.DeleteEvent += new DeleteEventHandler (Window_Delete);
win.SizeAllocated += new SizeAllocatedHandler (Size_Allocated); win.SizeAllocated += new SizeAllocatedHandler (Size_Allocated);
win.SizeRequested += new SizeRequestedHandler (Size_Requested);
win.ShowAll (); win.ShowAll ();
Application.Run (); Application.Run ();
return 0; return 0;
@ -29,6 +30,14 @@ namespace GtkSamples {
args.RetVal = true; args.RetVal = true;
} }
static void Size_Requested (object obj, SizeRequestedArgs args)
{
Requisition req = args.Requisition;
Console.WriteLine ("Requesting 100 x 100");
req.Width = req.Height = 100;
args.Requisition = req;
}
static void Size_Allocated (object obj, SizeAllocatedArgs args) static void Size_Allocated (object obj, SizeAllocatedArgs args)
{ {
Rectangle rect = args.Allocation; Rectangle rect = args.Allocation;