2003-04-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>

* generator/CallbackGen.cs: the new generated wrappers have:
		-(optional) Field of the same type returned by the callback.
		-A call to RemoveIfNotAlive at the beginning. It returns true,
		return the dummy field.
		-Added an object to the ctor signature and pass it to the base
		class.

	* generator/Ctor.cs: added a Params property.

	* generator/Method.cs: set Static property in Parameters if the method
	is static.

	* generator/Parameters.cs: added Static property. The call creation of
	the delegate wrapper (if applicable) uses the new signature. Pass a null
	as object is the method is static.

	* generator/StructBase.cs: set Static for the parameters of the ctors.

	* glib/DelegateWrapper.cs: the ctor takes an object (the one creating
	the wrapper or null) and creates a weak reference to it. Store it in
	a static Hashtable (this way the wrapper itself is not garbage
	collected).
	(RemoveIfNotAlive): called from the native delegate callbacks. If the
	target of the weak reference has been garbage collected, removes itself
	from the hashtable to let the GC dispose this instance and returns true.

	* gdk/Pixbuf.custom:
	* gtk/Clipboard.custom:
	* gtk/GtkSharp.GtkClipboardClearFuncNative.cs:
	* gtk/GtkSharp.GtkClipboardGetFuncNative.cs:
	* glade/XML.custom: changed delegate wrappers to match the new
	signature.

svn path=/trunk/gtk-sharp/; revision=13237
This commit is contained in:
Gonzalo Paniagua Javier 2003-04-06 09:21:15 +00:00
parent f7495647c1
commit 3821938764
11 changed files with 80 additions and 14 deletions

View file

@ -82,7 +82,7 @@
public Pixbuf(byte [] data, bool has_alpha, int bits_per_sample, int width, int height, int rowstride, Gdk.PixbufDestroyNotify destroy_fn)
{
GdkSharp.PixbufDestroyNotifyWrapper destroy_fn_wrapper = null;
destroy_fn_wrapper = new GdkSharp.PixbufDestroyNotifyWrapper (destroy_fn);
destroy_fn_wrapper = new GdkSharp.PixbufDestroyNotifyWrapper (destroy_fn, this);
Raw = gdk_pixbuf_new_from_data(data, (int) Gdk.Colorspace.Rgb, has_alpha, bits_per_sample, width, height, rowstride, destroy_fn_wrapper.NativeDelegate, IntPtr.Zero);
}

View file

@ -84,15 +84,34 @@ namespace GtkSharp.Generation {
XmlElement ret_elem = Elem["return-type"];
string rettype = ret_elem.GetAttribute("type");
string m_ret = SymbolTable.GetMarshalReturnType (rettype);
ClassBase ret_wrapper = SymbolTable.GetClassGen (rettype);
sw.WriteLine ("\tpublic delegate " + m_ret + " " + wrapper + "(" + import_sig + ");");
sw.WriteLine ();
sw.WriteLine ("\tpublic class " + Name + "Wrapper : GLib.DelegateWrapper {");
if (m_ret != "void") {
if (SymbolTable.IsEnum (rettype)) {
sw.WriteLine ("\t\tstatic int _dummy;");
} else if (ret_wrapper != null && (ret_wrapper is ObjectGen || ret_wrapper is OpaqueGen)) {
// Do nothing
} else if (!SymbolTable.IsStruct (rettype) && !SymbolTable.IsBoxed (rettype)) {
sw.WriteLine ("\t\tstatic {0} _dummy;", s_ret);
}
}
sw.WriteLine ();
sw.WriteLine ("\t\tpublic " + m_ret + " NativeCallback (" + import_sig + ")");
sw.WriteLine ("\t\t{");
sw.Write ("\t\t\tif (RemoveIfNotAlive ()) return ");
if (SymbolTable.IsStruct (rettype) || SymbolTable.IsBoxed (rettype))
sw.WriteLine ("IntPtr.Zero;");
else if (ret_wrapper != null && (ret_wrapper is ObjectGen || ret_wrapper is OpaqueGen))
sw.WriteLine ("IntPtr.Zero;");
else
sw.WriteLine (m_ret != "void" ? "_dummy;" : ";");
int count = (parms != null) ? parms.Count : 0;
if (count > 0)
sw.WriteLine ("\t\t\tobject[] _args = new object[{0}];", count);
@ -129,8 +148,7 @@ namespace GtkSharp.Generation {
sw.Write ("\t\t\t");
string invoke = "_managed (" + call_str + ")";
if (m_ret != "void") {
ClassBase parm_wrapper = SymbolTable.GetClassGen (rettype);
if (parm_wrapper != null && (parm_wrapper is ObjectGen || parm_wrapper is OpaqueGen))
if (ret_wrapper != null && (ret_wrapper is ObjectGen || ret_wrapper is OpaqueGen))
sw.WriteLine ("return (({0}) {1}).Handle;", s_ret, invoke);
else if (SymbolTable.IsStruct (rettype) || SymbolTable.IsBoxed (rettype)) {
// Shoot. I have no idea what to do here.
@ -150,7 +168,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t\tprotected {0} _managed;", NS + "." + Name);
sw.WriteLine ();
sw.WriteLine ("\t\tpublic {0} ({1} managed) : base ()", Name + "Wrapper", NS + "." + Name);
sw.WriteLine ("\t\tpublic {0} ({1} managed, object o) : base (o)", Name + "Wrapper", NS + "." + Name);
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\tNativeDelegate = new {0} (NativeCallback);", wrapper);

View file

@ -31,6 +31,10 @@ namespace GtkSharp.Generation {
set { force_static = value; }
}
public Parameters Params {
get { return parms; }
}
public Ctor (string libname, XmlElement elem, ClassBase container_type) {
this.libname = libname;
this.elem = elem;

View file

@ -170,6 +170,7 @@ namespace GtkSharp.Generation {
is_set = ((parms != null && (parms.IsAccessor || (parms.Count == 1 && s_ret == "void"))) && (Name.Length > 3 && Name.Substring(0, 3) == "Set"));
if (parms != null) {
parms.Static = is_shared;
parms.CreateSignature (is_set);
sig = "(" + parms.Signature + ")";
isig = "(" + (is_shared ? "" : container_type.MarshalType + " raw, ") + parms.ImportSig + ");";

View file

@ -123,6 +123,7 @@ namespace GtkSharp.Generation {
private string signature;
private string signature_types;
private bool hide_data;
private bool is_static;
public Parameters (XmlElement elem) {
@ -169,6 +170,10 @@ namespace GtkSharp.Generation {
set { hide_data = value; }
}
public bool Static {
set { is_static = value; }
}
public bool Validate ()
{
foreach (XmlNode parm in elem.ChildNodes) {
@ -394,7 +399,7 @@ namespace GtkSharp.Generation {
{
sw.Write ("if ({0} != null) ", name);
}
sw.WriteLine ("{1}_wrapper = new {0} ({1});", type, name);
sw.WriteLine ("{1}_wrapper = new {0} ({1}, {2});", type, name, is_static ? "null" : "this");
}
}
}

View file

@ -262,7 +262,10 @@ namespace GtkSharp.Generation {
foreach (Ctor ctor in Ctors) {
ctor.ForceStatic = true;
if (ctor.Params != null)
ctor.Params.Static = true;
}
base.GenCtors (sw);
}

View file

@ -18,7 +18,7 @@
static public void SetCustomHandler (Glade.XMLCustomWidgetHandler handler)
{
callback_wrapper = new GladeSharp.XMLCustomWidgetHandlerWrapper (handler);
callback_wrapper = new GladeSharp.XMLCustomWidgetHandlerWrapper (handler, null);
glade_set_custom_handler (callback_wrapper.NativeDelegate, IntPtr.Zero);
}

View file

@ -1,8 +1,11 @@
// DelegateWrapper.cs - Delegate wrapper implementation
//
// Author: Rachel Hestilow <hestilow@ximian.com>
// Authors:
// Rachel Hestilow <hestilow@ximian.com>
// Gonzalo Panigua Javier <gonzalo@ximian.com>
//
// (c) 2002 Rachel Hestilow
// (c) 2003 Ximian, Inc. (http://www.ximian.com)
namespace GLib {
@ -17,10 +20,40 @@ namespace GLib {
/// Wrapper class for delegates.
/// </remarks>
public class DelegateWrapper {
static ArrayList _instances = new ArrayList ();
public class DelegateWrapper
{
// Keys in the hashtable are instances of classes derived from this one.
// Values are WeakReference instances to the object that creates the
// delegate or instances of derived classes (if created from static methods).
static Hashtable weakReferences = new Hashtable ();
// The object 'o' is the object that creates the instance of the DelegateWrapper
// derived class or null if created from a static method.
// Note that the instances will never be disposed if they are created in a static
// method.
protected DelegateWrapper (object o)
{
if (o == null)
o = this; // Never expires. Used in static methods.
protected DelegateWrapper () {
weakReferences [this] = new WeakReference (o);
}
// IMPORTANT: this method must be the first one called from the callback methods that
// are invoked from unmanaged code.
// If this method returns true, the object that created the delegate wrapper no longer
// exists and the instance of the delegate itself is removed from the hash table.
protected bool RemoveIfNotAlive ()
{
WeakReference r = null;
r = weakReferences [this] as WeakReference;
if (r != null && !r.IsAlive) {
weakReferences.Remove (this);
r = null;
}
return (r == null);
}
}
}

View file

@ -32,8 +32,8 @@
clipboard_objects[this_id] = data;
}
get_func_wrapper = new GtkSharp.GtkClipboardGetFuncWrapper (get_func);
clear_func_wrapper = new GtkSharp.GtkClipboardClearFuncWrapper (clear_func);
get_func_wrapper = new GtkSharp.GtkClipboardGetFuncWrapper (get_func, this);
clear_func_wrapper = new GtkSharp.GtkClipboardClearFuncWrapper (clear_func, this);
IntPtr list = IntPtr.Zero;

View file

@ -9,6 +9,7 @@ namespace GtkSharp {
public void NativeCallback (IntPtr clipboard, uint objid)
{
if (RemoveIfNotAlive ()) return;
object[] _args = new object[2];
_args[0] = (Gtk.Clipboard) GLib.Opaque.GetOpaque(clipboard);
if (_args[0] == null)
@ -21,7 +22,7 @@ namespace GtkSharp {
public GtkClipboardClearFuncNative NativeDelegate;
protected Gtk.ClipboardClearFunc _managed;
public GtkClipboardClearFuncWrapper (Gtk.ClipboardClearFunc managed) : base ()
public GtkClipboardClearFuncWrapper (Gtk.ClipboardClearFunc managed, object o) : base (o)
{
NativeDelegate = new GtkClipboardClearFuncNative (NativeCallback);
_managed = managed;

View file

@ -9,6 +9,7 @@ namespace GtkSharp {
public void NativeCallback (IntPtr clipboard, ref Gtk.SelectionData selection_data, uint info, uint obj_id)
{
if (RemoveIfNotAlive ()) return;
object[] _args = new object[4];
_args[0] = (Gtk.Clipboard) GLib.Opaque.GetOpaque(clipboard);
if (_args[0] == null)
@ -23,7 +24,7 @@ namespace GtkSharp {
public GtkClipboardGetFuncNative NativeDelegate;
protected Gtk.ClipboardGetFunc _managed;
public GtkClipboardGetFuncWrapper (Gtk.ClipboardGetFunc managed) : base ()
public GtkClipboardGetFuncWrapper (Gtk.ClipboardGetFunc managed, object o) : base (o)
{
NativeDelegate = new GtkClipboardGetFuncNative (NativeCallback);
_managed = managed;