From 74105a1c80a99828c14a0295c606d27ac5b0e600 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Thu, 6 Nov 2008 02:23:21 +0000 Subject: [PATCH] 2008-11-05 Mike Kestner * atk/atk-api-2.12.raw: regen * gtk/gtk-api-2.12.raw: regen * generator/Signal.cs: reinstate old custom marshaler generation and generate custom marshaling when 'manual' attr is set. * parser/gapi2xml.pl: set manual attr on sigs that have G_TYPE_POINTER parameters since the generic closure can't cope with them. svn path=/trunk/gtk-sharp/; revision=118068 --- ChangeLog | 9 ++++ atk/atk-api-2.12.raw | 6 +-- generator/Signal.cs | 122 +++++++++++++++++++++++++++++++++++++++++-- gtk/gtk-api-2.12.raw | 15 ++++-- parser/gapi2xml.pl | 1 + 5 files changed, 140 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index b22cf457d..5368e9417 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-11-05 Mike Kestner + + * atk/atk-api-2.12.raw: regen + * gtk/gtk-api-2.12.raw: regen + * generator/Signal.cs: reinstate old custom marshaler generation and + generate custom marshaling when 'manual' attr is set. + * parser/gapi2xml.pl: set manual attr on sigs that have G_TYPE_POINTER + parameters since the generic closure can't cope with them. + 2008-11-05 Mike Kestner * gtk/Builder.custom: #if the new API for 2.14 for now so it diff --git a/atk/atk-api-2.12.raw b/atk/atk-api-2.12.raw index 3f7bfbe5a..a33144742 100644 --- a/atk/atk-api-2.12.raw +++ b/atk/atk-api-2.12.raw @@ -2214,7 +2214,7 @@ - + @@ -2229,7 +2229,7 @@ - + @@ -2250,7 +2250,7 @@ - + diff --git a/generator/Signal.cs b/generator/Signal.cs index 868394683..562e707c7 100644 --- a/generator/Signal.cs +++ b/generator/Signal.cs @@ -30,21 +30,27 @@ namespace GtkSharp.Generation { public class Signal { - private string name; - private XmlElement elem; - private ReturnValue retval; - private Parameters parms; - private ClassBase container_type; + bool marshaled; + string name; + XmlElement elem; + ReturnValue retval; + Parameters parms; + ClassBase container_type; public Signal (XmlElement elem, ClassBase container_type) { this.elem = elem; name = elem.GetAttribute ("name"); + marshaled = elem.GetAttribute ("manual") == "true"; retval = new ReturnValue (elem ["return-type"]); parms = new Parameters (elem["parameters"]); this.container_type = container_type; } + bool Marshaled { + get { return marshaled; } + } + public string Name { get { return name; @@ -85,6 +91,31 @@ namespace GtkSharp.Generation { } } + string CallbackSig { + get { + string result = ""; + for (int i = 0; i < parms.Count; i++) { + if (i > 0) + result += ", "; + + Parameter p = parms [i]; + if (p.PassAs != "" && !(p.Generatable is StructBase)) + result += p.PassAs + " "; + result += (p.MarshalType + " arg" + i); + } + + return result; + } + } + + string CallbackName { + get { return Name + "SignalCallback"; } + } + + string DelegateName { + get { return Name + "SignalDelegate"; } + } + private string EventArgsName { get { if (IsEventHandler) @@ -175,6 +206,82 @@ namespace GtkSharp.Generation { } } + public string GenArgsInitialization (StreamWriter sw) + { + if (parms.Count > 1) + sw.WriteLine("\t\t\t\targs.Args = new object[" + (parms.Count - 1) + "];"); + string finish = ""; + for (int idx = 1; idx < parms.Count; idx++) { + Parameter p = parms [idx]; + IGeneratable igen = p.Generatable; + if (p.PassAs != "out") { + if (igen is ManualGen) { + sw.WriteLine("\t\t\t\tif (arg{0} == IntPtr.Zero)", idx); + sw.WriteLine("\t\t\t\t\targs.Args[{0}] = null;", idx - 1); + sw.WriteLine("\t\t\t\telse {"); + sw.WriteLine("\t\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx) + ";"); + sw.WriteLine("\t\t\t\t}"); + } else + sw.WriteLine("\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx) + ";"); + } + if (igen is StructBase && p.PassAs == "ref") + finish += "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + (idx-1) + "], arg" + idx + ", false);\n"; + else if (p.PassAs != "") + finish += "\t\t\t\targ" + idx + " = " + igen.ToNativeReturn ("((" + p.CSType + ")args.Args[" + (idx - 1) + "])") + ";\n"; + } + return finish; + } + + public void GenArgsCleanup (StreamWriter sw, string finish) + { + if (IsVoid && finish.Length == 0) + return; + + sw.WriteLine("\n\t\t\ttry {"); + sw.Write (finish); + if (!IsVoid) { + if (retval.CSType == "bool") { + sw.WriteLine ("\t\t\t\tif (args.RetVal == null)"); + sw.WriteLine ("\t\t\t\t\treturn false;"); + } + sw.WriteLine("\t\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, "((" + retval.CSType + ")args.RetVal)") + ";"); + } + sw.WriteLine("\t\t\t} catch (Exception) {"); + sw.WriteLine ("\t\t\t\tException ex = new Exception (\"args.RetVal or 'out' property unset or set to incorrect type in " + EventHandlerQualifiedName + " callback\");"); + sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (ex, true);"); + + sw.WriteLine ("\t\t\t\t// NOTREACHED: above call doesn't return."); + sw.WriteLine ("\t\t\t\tthrow ex;"); + sw.WriteLine("\t\t\t}"); + } + + public void GenCallback (StreamWriter sw) + { + if (IsEventHandler) + return; + + sw.WriteLine ("\t\t[GLib.CDeclCallback]"); + sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + DelegateName + " (" + CallbackSig + ", IntPtr gch);"); + sw.WriteLine (); + sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + CallbackName + " (" + CallbackSig + ", IntPtr gch)"); + sw.WriteLine("\t\t{"); + sw.WriteLine("\t\t\t{0} args = new {0} ();", EventArgsQualifiedName); + sw.WriteLine("\t\t\ttry {"); + sw.WriteLine("\t\t\t\tGLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal;"); + sw.WriteLine("\t\t\t\tif (sig == null)"); + sw.WriteLine("\t\t\t\t\tthrow new Exception(\"Unknown signal GC handle received \" + gch);"); + sw.WriteLine(); + string finish = GenArgsInitialization (sw); + sw.WriteLine("\t\t\t\t{0} handler = ({0}) sig.Handler;", EventHandlerQualifiedName); + sw.WriteLine("\t\t\t\thandler (GLib.Object.GetObject (arg0), args);"); + sw.WriteLine("\t\t\t} catch (Exception e) {"); + sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, false);"); + sw.WriteLine("\t\t\t}"); + GenArgsCleanup (sw, finish); + sw.WriteLine("\t\t}"); + sw.WriteLine(); + } + private bool NeedNew (ClassBase implementor) { return elem.HasAttribute ("new_flag") || @@ -449,6 +556,11 @@ namespace GtkSharp.Generation { public void GenEvent (StreamWriter sw, ClassBase implementor, string target) { string args_type = IsEventHandler ? "" : ", typeof (" + EventArgsQualifiedName + ")"; + + if (Marshaled) { + GenCallback (sw); + args_type = ", new " + DelegateName + "(" + CallbackName + ")"; + } sw.WriteLine("\t\t[GLib.Signal("+ CName + ")]"); sw.Write("\t\tpublic "); diff --git a/gtk/gtk-api-2.12.raw b/gtk/gtk-api-2.12.raw index d4eb29531..42680184b 100644 --- a/gtk/gtk-api-2.12.raw +++ b/gtk/gtk-api-2.12.raw @@ -1001,6 +1001,11 @@ + + + + + @@ -1627,7 +1632,7 @@ - + @@ -2588,7 +2593,7 @@ - + @@ -9539,7 +9544,7 @@ - + @@ -9960,7 +9965,7 @@ - + @@ -12987,7 +12992,7 @@ - + diff --git a/parser/gapi2xml.pl b/parser/gapi2xml.pl index 2ed65f1ab..c2a178432 100755 --- a/parser/gapi2xml.pl +++ b/parser/gapi2xml.pl @@ -947,6 +947,7 @@ sub addSignalElem $sig_elem->setAttribute('when', $1) if ($spec =~ /_RUN_(\w+)/); my $method = ""; + $sig_elem->setAttribute('manual', 'true') if ($spec =~ /G_TYPE_POINTER/); if ($spec =~ /_OFFSET\s*\(\w+,\s*(\w+)\)/) { $method = $1; $sig_elem->setAttribute('field_name', $1);