From 7d611f77e46b58ba1e025c1e408323d1f3cbafe0 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Tue, 8 Jul 2008 21:12:22 +0000 Subject: [PATCH] 2008-07-08 Mike Kestner Patch from Christian Hoff with a few minor tweaks. * generator/CallbackGen.cs: refactor to use ManagedCallString and drop a ton of redundant, half-baked code. * generator/ManagedCallString.cs: add Unconditional setup method for stuff that has to happen before the try block. Add "drop_first" concept so it can be reused by CallbackGen which doesn't drop first params. * generator/Signal.cs: use Unconditional method for prep. * generator/VirtualMethod.cs: use Unconditional method for prep. * gtk/Gtk.metadata: mark a ref param. [Fixes #394352] svn path=/trunk/gtk-sharp/; revision=107494 --- ChangeLog | 13 ++++++ generator/CallbackGen.cs | 81 +++++++++------------------------- generator/ManagedCallString.cs | 28 +++++++++--- generator/Signal.cs | 5 ++- generator/VirtualMethod.cs | 5 ++- gtk/Gtk.metadata | 1 + 6 files changed, 64 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 706ce41d8..dd5dc44cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-07-08 Mike Kestner + + Patch from Christian Hoff with a few minor tweaks. + * generator/CallbackGen.cs: refactor to use ManagedCallString + and drop a ton of redundant, half-baked code. + * generator/ManagedCallString.cs: add Unconditional setup + method for stuff that has to happen before the try block. + Add "drop_first" concept so it can be reused by CallbackGen + which doesn't drop first params. + * generator/Signal.cs: use Unconditional method for prep. + * generator/VirtualMethod.cs: use Unconditional method for prep. + * gtk/Gtk.metadata: mark a ref param. + 2008-06-28 Mike Kestner * gtk/Gtk.metadata: mark ListStore.Reorder array param. diff --git a/generator/CallbackGen.cs b/generator/CallbackGen.cs index 17b492e23..121f2bd7c 100644 --- a/generator/CallbackGen.cs +++ b/generator/CallbackGen.cs @@ -207,76 +207,37 @@ namespace GtkSharp.Generation { GenInvoker (gen_info, sw); sw.WriteLine ("\tinternal class " + Name + "Wrapper {"); sw.WriteLine (); + ManagedCallString call = new ManagedCallString (parms, false); sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + parms.ImportSignature + ")"); sw.WriteLine ("\t\t{"); + string unconditional = call.Unconditional ("\t\t\t"); + if (unconditional.Length > 0) + sw.WriteLine (unconditional); sw.WriteLine ("\t\t\ttry {"); + string call_setup = call.Setup ("\t\t\t\t"); + if (call_setup.Length > 0) + sw.WriteLine (call_setup); + if (retval.CSType == "void") + sw.WriteLine ("\t\t\t\tmanaged ({0});", call); + else + sw.WriteLine ("\t\t\t\t{0} __ret = managed ({1});", retval.CSType, call); + string finish = call.Finish ("\t\t\t\t"); + if (finish.Length > 0) + sw.WriteLine (finish); + sw.WriteLine ("\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();"); + if (retval.CSType != "void") + sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret")); - bool need_sep = false; - bool throws_error = false; - string call_str = ""; - string cleanup_str = ""; - for (int i = 0, idx = 0; i < parms.Count; i++) - { - Parameter p = parms [i]; - - if (p.CType == "GError**") { - sw.WriteLine ("\t\t\t\t" + p.Name + " = IntPtr.Zero;"); - throws_error = true; - continue; - } else if (parms.IsHidden (p)) - continue; - - IGeneratable gen = p.Generatable; - - sw.Write("\t\t\t\t" + p.CSType + " _arg" + idx); - if (p.PassAs == "out") { - sw.WriteLine(";"); - cleanup_str += "\t\t\t\t" + p.Name + " = " + gen.CallByName ("_arg" + idx) + ";\n"; - } else - sw.WriteLine(" = " + gen.FromNative (p.Name) + ";"); - - if (need_sep) - call_str += ", "; - else - need_sep = true; - call_str += String.Format ("{0} _arg{1}", p.PassAs, idx); - idx++; - } - - bool has_out_params = cleanup_str.Length > 0; - cleanup_str += "\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();\n"; - - sw.Write ("\t\t\t\t"); - string invoke = "managed (" + call_str + ")"; - if (retval.MarshalType != "void") { - sw.Write (retval.MarshalType + " ret = "); - cleanup_str += "\t\t\t\treturn ret;\n"; - - SymbolTable table = SymbolTable.Table; - ClassBase ret_wrapper = table.GetClassGen (retval.CType); - if (ret_wrapper != null && ret_wrapper is HandleBase) - sw.WriteLine ("(({0}) {1}).Handle;", retval.CSType, invoke); - else if (table.IsStruct (retval.CType) || table.IsBoxed (retval.CType)) { - // Shoot. I have no idea what to do here. - Console.WriteLine ("Struct return type {0} in callback {1}", retval.CType, CName); - sw.WriteLine ("IntPtr.Zero;"); - } else if (table.IsEnum (retval.CType)) - sw.WriteLine ("(int) {0};", invoke); - else - sw.WriteLine ("({0}) ({1});", retval.MarshalType, table.ToNativeReturn (retval.CType, invoke)); - } else - sw.WriteLine (invoke + ";"); - - sw.Write (cleanup_str); - bool fatal = (retval.MarshalType != "void" && retval.MarshalType != "bool") || has_out_params || throws_error; + /* If the function expects one or more "out" parameters(error parameters are excluded) or has a return value different from void and bool, exceptions + * thrown in the managed function have to be considered fatal meaning that an exception is to be thrown and the function call cannot not return + */ + bool fatal = (retval.MarshalType != "void" && retval.MarshalType != "bool") || call.HasOutParam; sw.WriteLine ("\t\t\t} catch (Exception e) {"); sw.WriteLine ("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + (fatal ? "true" : "false") + ");"); if (fatal) { sw.WriteLine ("\t\t\t\t// NOTREACHED: Above call does not return."); sw.WriteLine ("\t\t\t\tthrow e;"); } else if (retval.MarshalType == "bool") { - if (throws_error) - sw.WriteLine ("\t\t\t\terror = IntPtr.Zero;"); sw.WriteLine ("\t\t\t\treturn false;"); } sw.WriteLine ("\t\t\t}"); diff --git a/generator/ManagedCallString.cs b/generator/ManagedCallString.cs index 57bccdebf..646caf444 100644 --- a/generator/ManagedCallString.cs +++ b/generator/ManagedCallString.cs @@ -33,17 +33,17 @@ namespace GtkSharp.Generation { string user_data_param = null; string destroy_param = null; - public ManagedCallString (Parameters parms) + public ManagedCallString (Parameters parms, bool drop_first) { - for (int i = 1; i < parms.Count; i ++) { + for (int i = drop_first ? 1 : 0; i < parms.Count; i ++) { Parameter p = parms [i]; - if (p.IsLength && parms [i-1].IsString) + if (p.IsLength && i > 0 && parms [i-1].IsString) continue; else if (p.Scope == "notified") { user_data_param = parms[i+1].Name; destroy_param = parms[i+2].Name; i += 2; - } else if (p.IsUserData && parms [i-1].Generatable is CallbackGen) { + } else if (p.IsUserData && (i == parms.Count - 1) && (parms.HideData || parms [i-1].Generatable is CallbackGen)) { user_data_param = p.Name; continue; } else if (p is ErrorParameter) { @@ -61,13 +61,27 @@ namespace GtkSharp.Generation { } } + public bool HasOutParam { + get { + foreach (Parameter p in parms) { + if (p.PassAs == "out") + return true; + } + return false; + } + } + + public string Unconditional (string indent) { + string ret = ""; + if (error_param != null) + ret = indent + error_param + " = IntPtr.Zero;\n"; + return ret; + } + public string Setup (string indent) { string ret = ""; - if (error_param != null) - ret = indent + error_param + " = IntPtr.Zero;\n"; - for (int i = 0; i < parms.Count; i ++) { if ((bool)special[i] == false) continue; diff --git a/generator/Signal.cs b/generator/Signal.cs index 22ceead1d..2629c346b 100644 --- a/generator/Signal.cs +++ b/generator/Signal.cs @@ -380,7 +380,7 @@ namespace GtkSharp.Generation { StreamWriter glue; bool use_glue = gen_info.GlueEnabled && implementor == null && ClassFieldName.Length > 0; string glue_name = String.Empty; - ManagedCallString call = new ManagedCallString (parms); + ManagedCallString call = new ManagedCallString (parms, true); sw.WriteLine ("\t\t[GLib.CDeclCallback]"); sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + parms.ImportSignature + ");\n"); @@ -402,6 +402,9 @@ namespace GtkSharp.Generation { sw.WriteLine ("\t\tstatic {0} {1};\n", Name + "VMDelegate", Name + "VMCallback"); sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + parms.ImportSignature + ")"); sw.WriteLine ("\t\t{"); + string unconditional = call.Unconditional ("\t\t\t"); + if (unconditional.Length > 0) + sw.WriteLine (unconditional); sw.WriteLine ("\t\t\ttry {"); sw.WriteLine ("\t\t\t\t{0} {1}_managed = GLib.Object.GetObject ({1}, false) as {0};", implementor != null ? implementor.Name : container_type.Name, parms[0].Name); sw.Write (call.Setup ("\t\t\t\t")); diff --git a/generator/VirtualMethod.cs b/generator/VirtualMethod.cs index 79911012f..8c09704da 100644 --- a/generator/VirtualMethod.cs +++ b/generator/VirtualMethod.cs @@ -70,7 +70,7 @@ namespace GtkSharp.Generation { if (!Validate ()) return; - ManagedCallString call = new ManagedCallString (parms); + ManagedCallString call = new ManagedCallString (parms, true); string type = parms [0].CSType + "Implementor"; string name = parms [0].Name; string call_string = "__obj." + Name + " (" + call + ")"; @@ -84,6 +84,9 @@ namespace GtkSharp.Generation { sw.WriteLine (); sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + Name + "Callback (" + parms.ImportSignature + ")"); sw.WriteLine ("\t\t{"); + string unconditional = call.Unconditional ("\t\t\t"); + if (unconditional.Length > 0) + sw.WriteLine (unconditional); sw.WriteLine ("\t\t\ttry {"); sw.WriteLine ("\t\t\t\t" + type + " __obj = GLib.Object.GetObject (" + name + ", false) as " + type + ";"); sw.Write (call.Setup ("\t\t\t\t")); diff --git a/gtk/Gtk.metadata b/gtk/Gtk.metadata index fbec50d8a..bc716d87c 100644 --- a/gtk/Gtk.metadata +++ b/gtk/Gtk.metadata @@ -53,6 +53,7 @@ true 1 1 +ref 1 1 1