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:
parent
f7495647c1
commit
3821938764
11 changed files with 80 additions and 14 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 + ");";
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue