From d8fb820b89aa53c61908a276cc532e272e31c471 Mon Sep 17 00:00:00 2001
From: Mike Kestner <mkestner@gmail.com>
Date: Fri, 20 Apr 2007 15:38:47 +0000
Subject: [PATCH] 2007-04-20  Mike Kestner  <mkestner@novell.com>

	* generator/CallbackGen.cs : switch to NativeCallbackSignature.
	* generator/GenBase.cs : add NativeCallbackType member.
	* generator/IGeneratable.cs : add NativeCallbackType member.
	* generator/ManagedCallString.cs : add guarded post call struct
	marshaling back to the native struct.
	* generator/NativeCallbackSignature.cs : new parallel to ImportSignature
	but using NativeCallbackType instead of MarshalType.
	* generator/Signal.cs : switch vm and sig marshaler callbacks to
	NativeCallbackSignature. Perform guarding post call struct marshaling
	back to the native struct.
	* generator/Parameters.cs : add NativeCallbackType member.
	* generator/SimpleBase.cs : add NativeCallbackType member.
	* generator/StructBase.cs : add NativeCallbackType member using IntPtr
	to support NULL handling.
	* gtk/NodeCellDataFunc.cs : update native marshaler sig.

svn path=/trunk/gtk-sharp/; revision=76011
---
 ChangeLog                            | 18 +++++++++
 generator/CallbackGen.cs             |  8 ++--
 generator/GenBase.cs                 |  6 +++
 generator/IGeneratable.cs            |  7 +++-
 generator/Makefile.am                |  1 +
 generator/ManagedCallString.cs       |  5 ++-
 generator/NativeCallbackSignature.cs | 58 ++++++++++++++++++++++++++++
 generator/Parameters.cs              | 12 ++++++
 generator/Signal.cs                  | 15 ++++---
 generator/SimpleBase.cs              |  6 +++
 generator/StructBase.cs              | 23 +++++------
 gtk/NodeCellDataFunc.cs              |  3 +-
 12 files changed, 134 insertions(+), 28 deletions(-)
 create mode 100644 generator/NativeCallbackSignature.cs

diff --git a/ChangeLog b/ChangeLog
index c310dfd22..4c66a5c24 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-04-20  Mike Kestner  <mkestner@novell.com>
+
+	* generator/CallbackGen.cs : switch to NativeCallbackSignature.
+	* generator/GenBase.cs : add NativeCallbackType member.
+	* generator/IGeneratable.cs : add NativeCallbackType member.
+	* generator/ManagedCallString.cs : add guarded post call struct
+	marshaling back to the native struct.
+	* generator/NativeCallbackSignature.cs : new parallel to ImportSignature
+	but using NativeCallbackType instead of MarshalType.
+	* generator/Signal.cs : switch vm and sig marshaler callbacks to 
+	NativeCallbackSignature. Perform guarding post call struct marshaling
+	back to the native struct.
+	* generator/Parameters.cs : add NativeCallbackType member.
+	* generator/SimpleBase.cs : add NativeCallbackType member.
+	* generator/StructBase.cs : add NativeCallbackType member using IntPtr
+	to support NULL handling.
+	* gtk/NodeCellDataFunc.cs : update native marshaler sig.
+
 2007-04-17  Mike Kestner  <mkestner@novell.com>
 
 	* gtk/Gtk.metadata : hide TreeModel.RowsReordered signal so we can do
diff --git a/generator/CallbackGen.cs b/generator/CallbackGen.cs
index a0388fe16..48dec9681 100644
--- a/generator/CallbackGen.cs
+++ b/generator/CallbackGen.cs
@@ -30,7 +30,7 @@ namespace GtkSharp.Generation {
 
 		private Parameters parms;
 		private Signature sig = null;
-		private ImportSignature isig = null;
+		private NativeCallbackSignature native_sig = null;
 		private ReturnValue retval;
 		private bool valid = true;
 
@@ -92,7 +92,7 @@ namespace GtkSharp.Generation {
 			string wrapper = Name + "Native";
 			string qualname = MarshalType;
 
-			isig = new ImportSignature (parms);
+			native_sig = new NativeCallbackSignature (parms);
 
 			StreamWriter sw = gen_info.OpenStream (qualname);
 
@@ -103,11 +103,11 @@ namespace GtkSharp.Generation {
 			sw.WriteLine ();
 			sw.WriteLine ("#region Autogenerated code");
 			sw.WriteLine ("\t[GLib.CDeclCallback]");
-			sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + isig + ");");
+			sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + native_sig + ");");
 			sw.WriteLine ();
 			sw.WriteLine ("\tinternal class " + Name + "Wrapper {");
 			sw.WriteLine ();
-			sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + isig + ")");
+			sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + native_sig + ")");
 			sw.WriteLine ("\t\t{");
 			sw.WriteLine ("\t\t\ttry {");
 
diff --git a/generator/GenBase.cs b/generator/GenBase.cs
index d858407d0..7526fddc7 100644
--- a/generator/GenBase.cs
+++ b/generator/GenBase.cs
@@ -63,6 +63,12 @@ namespace GtkSharp.Generation {
 
 		public abstract string MarshalType { get; }
 
+		public virtual string NativeCallbackType { 
+			get {
+				return MarshalType;
+			}
+		}
+
 		public string Name {
 			get {
 				return elem.GetAttribute ("name");
diff --git a/generator/IGeneratable.cs b/generator/IGeneratable.cs
index 001bc0afc..ae2e4f066 100644
--- a/generator/IGeneratable.cs
+++ b/generator/IGeneratable.cs
@@ -1,8 +1,9 @@
 // GtkSharp.Generation.IGeneratable.cs - Interface to generate code for a type.
 //
-// Author: Mike Kestner <mkestner@speakeasy.net>
+// Author: Mike Kestner <mkestner@novell.com>
 //
 // Copyright (c) 2001 Mike Kestner
+// Copyright (c) 2007 Novell, Inc.
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of version 2 of the GNU General Public
@@ -36,6 +37,10 @@ namespace GtkSharp.Generation {
 		// signature when passing this generatable to unmanaged code
 		string MarshalType {get;}
 
+		// The type to use in the native delegate signature when marshaling to
+		// managed code from a native callback.
+		string NativeCallbackType {get;}
+
 		// The type to use as the return type in an import signature when
 		// receiving this generatable back from unmanaged code
 		string MarshalReturnType {get;}
diff --git a/generator/Makefile.am b/generator/Makefile.am
index a753ff065..d1e0a3bb0 100644
--- a/generator/Makefile.am
+++ b/generator/Makefile.am
@@ -36,6 +36,7 @@ sources = 				\
 	MethodBase.cs			\
 	MethodBody.cs			\
 	Method.cs			\
+	NativeCallbackSignature.cs	\
 	ObjectField.cs			\
 	ObjectBase.cs			\
 	ObjectGen.cs			\
diff --git a/generator/ManagedCallString.cs b/generator/ManagedCallString.cs
index e1a720936..dfecc4da5 100644
--- a/generator/ManagedCallString.cs
+++ b/generator/ManagedCallString.cs
@@ -94,7 +94,10 @@ namespace GtkSharp.Generation {
 				Parameter p = parms [i] as Parameter;
 				IGeneratable igen = p.Generatable;
 
-				ret += indent + p.Name + " = " + igen.CallByName ("my" + p.Name) + ";\n";
+				if (igen is StructBase)
+					ret += indent + String.Format ("if ({0} != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (my{0}, {0}, false);\n", p.Name);
+				else
+					ret += indent + p.Name + " = " + igen.ToNativeReturn ("my" + p.Name) + ";\n";
 			}
 
 			return ret;
diff --git a/generator/NativeCallbackSignature.cs b/generator/NativeCallbackSignature.cs
new file mode 100644
index 000000000..d62fb390c
--- /dev/null
+++ b/generator/NativeCallbackSignature.cs
@@ -0,0 +1,58 @@
+// GtkSharp.Generation.NativeCallbackSignature.cs - The NativeCallbackSignature Generation Class.
+//
+// Author: Mike Kestner <mkestner@novell.com>
+//
+// Copyright (c) 2007 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+
+	public class NativeCallbackSignature {
+
+		Parameters parameters;
+
+		public NativeCallbackSignature (Parameters parms) 
+		{
+			parameters = parms;
+		}
+
+		public override string ToString ()
+		{
+			if (parameters.Count == 0)
+				return "";
+
+			string[] parms = new string [parameters.Count];
+			for (int i = 0; i < parameters.Count; i++) {
+				Parameter p = parameters [i];
+
+				parms [i] = "";
+				if (p.CType == "GError**")
+					parms [i] += "out ";
+				else if (p.PassAs != "")
+					parms [i] += p.PassAs + " ";
+				parms [i] += p.NativeCallbackType + " " + p.Name;
+			}
+
+			string import_sig = String.Join (", ", parms);
+			return import_sig;
+		}
+	}
+}
+
diff --git a/generator/Parameters.cs b/generator/Parameters.cs
index 564b3678f..9d53b535e 100644
--- a/generator/Parameters.cs
+++ b/generator/Parameters.cs
@@ -155,6 +155,18 @@ namespace GtkSharp.Generation {
 			}
 		}
 
+		public string NativeCallbackType {
+			get {
+				string type = Generatable.NativeCallbackType;
+				if (type == "void")
+					type = "System.IntPtr";
+				if (IsArray) {
+					type += "[]";
+					type = type.Replace ("ref ", "");
+				}
+				return type;
+			}
+		}
 		public string Name {
 			get {
 				return SymbolTable.Table.MangleName (elem.GetAttribute("name"));
diff --git a/generator/Signal.cs b/generator/Signal.cs
index 7af990823..92c9c18b4 100644
--- a/generator/Signal.cs
+++ b/generator/Signal.cs
@@ -100,13 +100,10 @@ namespace GtkSharp.Generation {
 
 					if (parms[i].PassAs != "")
 						result += parms[i].PassAs + " ";
-					result += (parms[i].MarshalType + " arg" + i);
+					result += (parms[i].NativeCallbackType + " arg" + i);
 				}
 				result += ", IntPtr gch";
 
-				result = result.Replace ("out ref", "out");
-				result = result.Replace ("ref ref", "ref");
-
 				return result;
 			}
 		}
@@ -232,7 +229,9 @@ namespace GtkSharp.Generation {
 					} else
 						sw.WriteLine("\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx)  + ";");
 				}
-				if (p.PassAs != "")
+				if (igen is StructBase)
+					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";
 			}
 			sw.WriteLine("\t\t\t\t{0} handler = ({0}) sig.Handler;", EventHandlerQualifiedName);
@@ -372,12 +371,12 @@ namespace GtkSharp.Generation {
 
 		private void GenDefaultHandlerDelegate (StreamWriter sw, ClassBase implementor)
 		{
-			ImportSignature isig = new ImportSignature (parms);
+			NativeCallbackSignature sig = new NativeCallbackSignature (parms);
 			ManagedCallString call = new ManagedCallString (parms);
 			sw.WriteLine ("\t\t[GLib.CDeclCallback]");
-			sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + isig.ToString () + ");\n");
+			sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + sig.ToString () + ");\n");
 			sw.WriteLine ("\t\tstatic {0} {1};\n", Name + "VMDelegate", Name + "VMCallback");
-			sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + isig.ToString () + ")");
+			sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + sig.ToString () + ")");
 			sw.WriteLine ("\t\t{");
 			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);
diff --git a/generator/SimpleBase.cs b/generator/SimpleBase.cs
index b30513778..b9f145141 100644
--- a/generator/SimpleBase.cs
+++ b/generator/SimpleBase.cs
@@ -64,6 +64,12 @@ namespace GtkSharp.Generation {
 			}
 		}
 
+		public virtual string NativeCallbackType {
+			get {
+				return MarshalType;
+			}
+		}
+
 		public virtual string MarshalReturnType {
 			get {
 				return MarshalType;
diff --git a/generator/StructBase.cs b/generator/StructBase.cs
index bb056c361..57fc410a9 100644
--- a/generator/StructBase.cs
+++ b/generator/StructBase.cs
@@ -56,22 +56,25 @@ namespace GtkSharp.Generation {
 		}
 
 		public override string MarshalType {
-			get
-			{
+			get {
 				return "ref " + QualifiedName;
 			}
 		}
 
+		public override string NativeCallbackType {
+			get {
+				return "IntPtr";
+			}
+		}
+
 		public override string MarshalReturnType {
-			get
-			{
+			get {
 				return "IntPtr";
 			}
 		}
 
 		public override string ToNativeReturnType {
-			get
-			{
+			get {
 				return QualifiedName;
 			}
 		}
@@ -91,18 +94,12 @@ namespace GtkSharp.Generation {
 		}
 
 		public override string FromNative(string var)
-		{
-			return var;
-		}
-		
-		public override string FromNativeReturn(string var)
 		{
 			return QualifiedName + ".New (" + var + ")";
 		}
-
+		
 		public override string ToNativeReturn(string var)
 		{
-			// FIXME
 			return var;
 		}
 
diff --git a/gtk/NodeCellDataFunc.cs b/gtk/NodeCellDataFunc.cs
index e79bcf3d9..5c1b3b193 100644
--- a/gtk/NodeCellDataFunc.cs
+++ b/gtk/NodeCellDataFunc.cs
@@ -28,11 +28,12 @@ namespace Gtk {
 
 	internal class NodeCellDataFuncWrapper {
 
-		public void NativeCallback (IntPtr tree_column, IntPtr cell, IntPtr tree_model, ref Gtk.TreeIter iter, IntPtr data)
+		public void NativeCallback (IntPtr tree_column, IntPtr cell, IntPtr tree_model, IntPtr iter_ptr, IntPtr data)
 		{
 			TreeViewColumn col = (Gtk.TreeViewColumn) GLib.Object.GetObject(tree_column);
 			CellRenderer renderer = (Gtk.CellRenderer) GLib.Object.GetObject(cell);
 			NodeStore store = (NodeStore) GLib.Object.GetObject(tree_model);
+			TreeIter iter = TreeIter.New (iter_ptr);
 			managed (col,  renderer,  store.GetNode (iter));
 		}