diff --git a/ChangeLog b/ChangeLog index 750a505f1..87b0b30f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2003-07-23 Mike Kestner + + [Equal credit to Ettore Perazzoli for fixing + all the bugs in the initial patch] + * */*.custom : fix incorrect usage of new Object (IntPtr) where + Glib.Object.GetObject should've been used. add ref_owned param + to GetObject calls. + * generator/CallbackGen.cs : setup ref_owned in bodies + * generator/ClassBase.cs : add ref_owned to GetObject FromNative call + * generator/Method.cs : setup ref_owned in bodies + * generator/Property.cs : setup ref_owned in bodies + * generator/SignalHandler.cs : pass ref_owned to GetObject + * generator/StructBase.cs : setup ref_owned in bodies + * glib/Object.cs : kill Ref/Unref methods. Don't want it to be + easy for users to screw with ref counts, or make it look like they + should need to. + (GetObject): add ref_owned param and ref/unref to remain at 1 + * glib/Value.cs : pass ref_owned to GetObject + 2003-07-23 Martin Willemoes Hansen * generator/ClassBase.cs: Fixed printouts of ctor validation. diff --git a/gdk/Pixbuf.custom b/gdk/Pixbuf.custom index 89c86c42d..dd7cacfc9 100644 --- a/gdk/Pixbuf.custom +++ b/gdk/Pixbuf.custom @@ -33,18 +33,13 @@ Raw = LoadFromStream (s); } - // scale_simple, composite_color_simple, and addalpha do a gdk_pixbuf_new on the - // return first, and we also ref it - // in the GetObject. So get rid of one extra reference. - [DllImport("gdk_pixbuf-2.0")] static extern IntPtr gdk_pixbuf_scale_simple(IntPtr raw, int dest_width, int dest_height, int interp_type); public Gdk.Pixbuf ScaleSimple(int dest_width, int dest_height, Gdk.InterpType interp_type) { IntPtr raw_ret = gdk_pixbuf_scale_simple(Handle, dest_width, dest_height, (int) interp_type); - Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret); - ret.Unref (); + Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true); return ret; } @@ -53,8 +48,7 @@ public Gdk.Pixbuf CompositeColorSimple(int dest_width, int dest_height, Gdk.InterpType interp_type, int overall_alpha, int check_size, uint color1, uint color2) { IntPtr raw_ret = gdk_pixbuf_composite_color_simple(Handle, dest_width, dest_height, (int) interp_type, overall_alpha, check_size, color1, color2); - Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret); - ret.Unref (); + Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true); return ret; } @@ -63,8 +57,7 @@ public Gdk.Pixbuf AddAlpha(bool substitute_color, byte r, byte g, byte b) { IntPtr raw_ret = gdk_pixbuf_add_alpha(Handle, substitute_color, r, g, b); - Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret); - ret.Unref (); + Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true); return ret; } diff --git a/generator/CallbackGen.cs b/generator/CallbackGen.cs index 030f88ef1..98dae575a 100644 --- a/generator/CallbackGen.cs +++ b/generator/CallbackGen.cs @@ -127,6 +127,7 @@ namespace GtkSharp.Generation { sw.WriteLine ("\t\t\tobject[] _args = new object[{0}];", count); int idx = 0; bool need_sep = false; + bool need_ref_owned = true; string call_str = ""; for (int i = 0; i < count; i++) { @@ -142,6 +143,10 @@ namespace GtkSharp.Generation { string cstype = parms[i].CSType; // FIXME: Too much code copy/pasted here. Refactor? ClassBase parm_wrapper = table.GetClassGen (ctype); + if (need_ref_owned && parm_wrapper != null && ((parm_wrapper is ObjectGen) || (parm_wrapper is InterfaceGen))) { + need_ref_owned = false; + sw.WriteLine("\t\t\tbool ref_owned = false;"); + } sw.WriteLine("\t\t\t_args[" + idx + "] = " + table.FromNative (ctype, parm_name) + ";"); if ((parm_wrapper != null && ((parm_wrapper is OpaqueGen))) || table.IsManuallyWrapped (ctype)) { sw.WriteLine("\t\t\tif (_args[" + idx + "] == null)"); diff --git a/generator/ClassBase.cs b/generator/ClassBase.cs index 02fb4f95c..40a3e6d4f 100644 --- a/generator/ClassBase.cs +++ b/generator/ClassBase.cs @@ -134,7 +134,7 @@ namespace GtkSharp.Generation { public virtual String FromNative(String var) { - return "(" + QualifiedName + ") GLib.Object.GetObject(" + var + ")"; + return "(" + QualifiedName + ") GLib.Object.GetObject(" + var + ", ref_owned)"; } public virtual String FromNativeReturn(String var) diff --git a/generator/Method.cs b/generator/Method.cs index 7f3ce9534..687cd56d3 100644 --- a/generator/Method.cs +++ b/generator/Method.cs @@ -391,9 +391,9 @@ namespace GtkSharp.Generation { if (table.IsObject (rettype) || table.IsOpaque (rettype)) { sw.WriteLine(m_ret + " raw_ret = " + cname + call + ";"); + if (table.IsObject (rettype)) + sw.WriteLine(indent + "\t\t\tbool ref_owned = false;"); sw.WriteLine(indent +"\t\t\t" + s_ret + " ret = " + table.FromNativeReturn(rettype, "raw_ret") + ";"); - if (needs_ref) - sw.WriteLine(indent + "\t\t\tret.Ref ();"); if (table.IsOpaque (rettype)) sw.WriteLine(indent + "\t\t\tif (ret == null) ret = new " + s_ret + "(raw_ret);"); } @@ -403,6 +403,8 @@ namespace GtkSharp.Generation { string raw_parms = "raw_ret"; if (element_type != null) raw_parms += ", typeof (" + element_type + ")"; + if (table.IsInterface (rettype)) + sw.WriteLine(indent + "\t\t\tbool ref_owned = false;"); sw.WriteLine(s_ret + " ret = " + table.FromNativeReturn(rettype, raw_parms) + ";"); } } diff --git a/generator/Property.cs b/generator/Property.cs index 5418a0c2f..e9defdd6b 100644 --- a/generator/Property.cs +++ b/generator/Property.cs @@ -123,6 +123,8 @@ namespace GtkSharp.Generation { sw.WriteLine("\t\t\t\tGetProperty(" + cname + ", val);"); if (table.IsObject (c_type) || table.IsOpaque (c_type) || table.IsBoxed (c_type)) { sw.WriteLine("\t\t\t\tSystem.IntPtr raw_ret = (System.IntPtr) {0} val;", v_type); + if (table.IsObject (c_type)) + sw.WriteLine ("\t\t\t\tbool ref_owned = false;"); sw.WriteLine("\t\t\t\t" + cs_type + " ret = " + table.FromNativeReturn(c_type, "raw_ret") + ";"); if (!table.IsBoxed (c_type)) sw.WriteLine("\t\t\t\tif (ret == null) ret = new " + cs_type + "(raw_ret);"); diff --git a/generator/SignalHandler.cs b/generator/SignalHandler.cs index 2f29daa14..746331ba7 100644 --- a/generator/SignalHandler.cs +++ b/generator/SignalHandler.cs @@ -140,7 +140,7 @@ namespace GtkSharp.Generation { sw.WriteLine("\t\t\t\targs.Args[{0}] = null;", idx - 1); sw.WriteLine("\t\t\telse {"); if (wrapper != null && wrapper is ObjectGen) - sw.WriteLine("\t\t\t\targs.Args[" + (idx-1) + "] = GLib.Object.GetObject(arg" + idx + ");"); + sw.WriteLine("\t\t\t\targs.Args[" + (idx-1) + "] = GLib.Object.GetObject(arg" + idx + ", true);"); else sw.WriteLine("\t\t\t\targs.Args[" + (idx-1) + "] = " + table.FromNative (ctype, "arg" + idx) + ";"); if ((wrapper != null && (wrapper is OpaqueGen)) || table.IsManuallyWrapped (ctype)) { diff --git a/generator/StructBase.cs b/generator/StructBase.cs index f92c7ede5..08f3bbb0f 100644 --- a/generator/StructBase.cs +++ b/generator/StructBase.cs @@ -163,8 +163,8 @@ namespace GtkSharp.Generation { sw.WriteLine (); sw.WriteLine ("\t\tpublic " + wrapped + " " + wrapped_name + " {"); sw.WriteLine ("\t\t\tget { "); + sw.WriteLine ("\t\t\t\tbool ref_owned = false;"); sw.WriteLine ("\t\t\t\t" + wrapped + " ret = " + table.FromNativeReturn(c_type, name) + ";"); - sw.WriteLine ("\t\t\t\tret.Ref ();"); sw.WriteLine ("\t\t\t\treturn ret;"); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\tset { " + name + " = " + table.CallByName (c_type, "value") + "; }"); diff --git a/glade/XML.custom b/glade/XML.custom index ab117967b..4072f64a3 100644 --- a/glade/XML.custom +++ b/glade/XML.custom @@ -56,7 +56,7 @@ static public Glade.XML GetWidgetTree (Gtk.Widget w) { IntPtr ret_raw = glade_get_widget_tree (w.Handle); - Glade.XML ret = GLib.Object.GetObject (ret_raw) as Glade.XML; + Glade.XML ret = GLib.Object.GetObject (ret_raw, false) as Glade.XML; return ret; } @@ -165,13 +165,13 @@ string signal_name, string signal_data, IntPtr connect_object_ptr, int after, IntPtr user_data) { - GLib.Object objekt = GLib.Object.GetObject (objekt_ptr); + GLib.Object objekt = GLib.Object.GetObject (objekt_ptr, false); /* if an connect_object_ptr is provided, use that as handler */ object connect_object = connect_object_ptr == IntPtr.Zero ? handler_object - : GLib.Object.GetObject (connect_object_ptr); + : GLib.Object.GetObject (connect_object_ptr, false); /* search for the event to connect */ System.Reflection.MemberInfo[] evnts = objekt.GetType (). diff --git a/glib/ListBase.cs b/glib/ListBase.cs index 6f185f57c..bbbf58ce5 100644 --- a/glib/ListBase.cs +++ b/glib/ListBase.cs @@ -145,7 +145,7 @@ namespace GLib { ret = Activator.CreateInstance (list.element_type, new object[] {data}); } else if (Object.IsObject (data)) - ret = GLib.Object.GetObject (data); + ret = GLib.Object.GetObject (data, true); return ret; } diff --git a/glib/Object.cs b/glib/Object.cs index 98cf9d548..af5b4eefe 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -1,9 +1,8 @@ // Object.cs - GObject class wrapper implementation // -// Authors: Bob Smith -// Mike Kestner +// Authors: Mike Kestner // -// (c) 2001 Bob Smith and Mike Kestner +// (c) 2001-2003 Mike Kestner // // TODO: // Could remove `disposed' for a check if an object is on the dispose_queue_list. @@ -34,7 +33,6 @@ namespace GLib { // Private class and instance members IntPtr _obj; - protected bool needs_ref = true; EventHandlerList _events; bool disposed = false; Hashtable data; @@ -50,6 +48,9 @@ namespace GLib { Dispose (); } + [DllImport("libgobject-2.0-0.dll")] + static extern void g_object_unref (IntPtr raw); + static bool PerformQueuedUnrefs () { Object [] objects; @@ -66,7 +67,7 @@ namespace GLib { if (o._obj == IntPtr.Zero) continue; - o.Unref (); + g_object_unref (o._obj); o._obj = IntPtr.Zero; } return false; @@ -101,49 +102,9 @@ namespace GLib { GC.SuppressFinalize (this); } - [DllImport("libgobject-2.0-0.dll")] - static extern void g_object_unref (IntPtr raw); - [DllImport("libgobject-2.0-0.dll")] static extern void g_object_ref (IntPtr raw); - /// - /// Ref Method - /// - /// - /// - /// Increases the reference count on the native object. - /// This method is used by generated classes and structs, - /// and should not be used in user code. - /// - public virtual void Ref () - { - if (_obj == IntPtr.Zero) - return; - - g_object_ref (_obj); - } - - /// - /// Unref Method - /// - /// - /// - /// Decreases the reference count on the native object. - /// This method is used by generated classes and structs, - /// and should not be used in user code. - /// - /// This method should not be invoked by a thread. - /// - public virtual void Unref () - { - if (_obj == IntPtr.Zero) - return; - - g_object_unref (_obj); - } - - /// /// GetObject Shared Method /// @@ -160,24 +121,40 @@ namespace GLib { /// The wrapper instance. /// - public static Object GetObject(IntPtr o) + public static Object GetObject(IntPtr o, bool owned_ref) { - WeakReference obj = Objects[o] as WeakReference; - if (obj != null) { - // If the target object has not been collected, use it... - if (obj.IsAlive) - return obj.Target as GLib.Object; - - // ... otherwise we create a new wrapper around the IntPtr. - Objects [o] = null; + Object obj; + WeakReference weak_ref = Objects[o] as WeakReference; + if (weak_ref != null && weak_ref.IsAlive) { + obj = weak_ref.Target as GLib.Object; + if (owned_ref) + g_object_unref (obj._obj); + return obj; } - return GtkSharp.ObjectManager.CreateObject(o); + obj = GtkSharp.ObjectManager.CreateObject(o); + if (obj == null) + return null; + + if (!owned_ref) + g_object_ref (obj.Handle); + Objects [o] = new WeakReference (obj); + return obj; } [DllImport("gtksharpglue")] static extern uint gtksharp_register_type (string name, uint parent_type); + /// + /// RegisterGType Shared Method + /// + /// + /// + /// Shared method to register types with the GType system. + /// This method should be called from the class constructor + /// of subclasses. + /// + public static GLib.Type RegisterGType (System.Type t) { System.Type parent = t.BaseType; @@ -200,9 +177,7 @@ namespace GLib { /// Dummy constructor needed for derived classes. /// - public Object () { - needs_ref = false; - } + protected Object () {} /// /// Object Constructor @@ -220,7 +195,15 @@ namespace GLib { [DllImport("libgobject-2.0-0.dll")] static extern IntPtr g_object_new (uint gtype, IntPtr dummy); - public Object (GLib.Type gtype) + /// + /// Object Constructor + /// + /// + /// + /// Creates an object from a specified GType. + /// + + protected Object (GLib.Type gtype) { Raw = g_object_new (gtype.Value, IntPtr.Zero); } @@ -241,8 +224,6 @@ namespace GLib { return _obj; } set { - if (needs_ref) - g_object_ref (value); Objects [value] = new WeakReference (this); _obj = value; } diff --git a/glib/Value.cs b/glib/Value.cs index 8a1b08660..a54cde52a 100755 --- a/glib/Value.cs +++ b/glib/Value.cs @@ -475,7 +475,7 @@ namespace GLib { { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. - return GLib.Object.GetObject(g_value_get_object (val._val)); + return GLib.Object.GetObject(g_value_get_object (val._val), true); } /// diff --git a/gnome/CanvasItem.custom b/gnome/CanvasItem.custom index e60c02552..dcb2d2ae4 100644 --- a/gnome/CanvasItem.custom +++ b/gnome/CanvasItem.custom @@ -12,13 +12,17 @@ [DllImport("gnomecanvas-2")] static extern System.IntPtr gnome_canvas_item_new (IntPtr group, uint type, IntPtr null_terminator); +[DllImport("libgobject-2.0-0.dll")] +static extern void g_object_ref (IntPtr raw); + public CanvasItem (Gnome.CanvasGroup group, uint type) : base (gnome_canvas_item_new (group.Handle, type, IntPtr.Zero)) { + g_object_ref (Handle); } [DllImport("gtksharpglue")] static extern IntPtr gtksharp_gnome_canvas_item_get_canvas (IntPtr i); public Canvas Canvas { - get { return new Gnome.Canvas (gtksharp_gnome_canvas_item_get_canvas (this.Handle)); } + get { return GLib.Object.GetObject (gtksharp_gnome_canvas_item_get_canvas (this.Handle), false) as Canvas; } } diff --git a/gtk/Combo.custom b/gtk/Combo.custom index 8f3d6586f..4f35df0c1 100644 --- a/gtk/Combo.custom +++ b/gtk/Combo.custom @@ -11,7 +11,7 @@ static extern IntPtr gtksharp_combo_get_entry(IntPtr i); public Gtk.Entry Entry { get { - return new Gtk.Entry (gtksharp_combo_get_entry(this.Handle)); + return GLib.Object.GetObject (gtksharp_combo_get_entry(this.Handle), false) as Gtk.Entry; } } @@ -20,6 +20,6 @@ static extern IntPtr gtksharp_combo_get_button(IntPtr i); public Gtk.Button Button { get { - return new Gtk.Button (gtksharp_combo_get_button(this.Handle)); + return GLib.Object.GetObject (gtksharp_combo_get_button(this.Handle), false) as Gtk.Button; } } diff --git a/gtk/Dialog.custom b/gtk/Dialog.custom index 0258565ac..ac3286eb6 100644 --- a/gtk/Dialog.custom +++ b/gtk/Dialog.custom @@ -20,12 +20,12 @@ public Dialog (string title, Gtk.Window parent, Gtk.DialogFlags flags) : base() [DllImport("gtksharpglue")] static extern IntPtr gtksharp_dialog_get_vbox (IntPtr i); public Gtk.VBox VBox { - get { return new Gtk.VBox (gtksharp_dialog_get_vbox (this.Handle)); } + get { return GLib.Object.GetObject (gtksharp_dialog_get_vbox (this.Handle), false) as VBox; } } [DllImport("gtksharpglue")] static extern IntPtr gtksharp_dialog_get_action_area (IntPtr i); public Gtk.VBox ActionArea { - get { return new Gtk.VBox (gtksharp_dialog_get_action_area (this.Handle)); } + get { return GLib.Object.GetObject (gtksharp_dialog_get_action_area (this.Handle), false) as VBox; } } diff --git a/gtk/GtkSharp.GtkClipboardClearFuncNative.cs b/gtk/GtkSharp.GtkClipboardClearFuncNative.cs index 965594aff..131d60541 100644 --- a/gtk/GtkSharp.GtkClipboardClearFuncNative.cs +++ b/gtk/GtkSharp.GtkClipboardClearFuncNative.cs @@ -11,7 +11,7 @@ namespace GtkSharp { { if (RemoveIfNotAlive ()) return; object[] _args = new object[2]; - _args[0] = (Gtk.Clipboard) GLib.Object.GetObject(clipboard); + _args[0] = (Gtk.Clipboard) GLib.Object.GetObject(clipboard, false); if (_args[0] == null) _args[0] = new Gtk.Clipboard(clipboard); _args[1] = Gtk.Clipboard.clipboard_objects[objid]; diff --git a/gtk/GtkSharp.GtkClipboardGetFuncNative.cs b/gtk/GtkSharp.GtkClipboardGetFuncNative.cs index 284af6149..9c5695535 100644 --- a/gtk/GtkSharp.GtkClipboardGetFuncNative.cs +++ b/gtk/GtkSharp.GtkClipboardGetFuncNative.cs @@ -11,7 +11,7 @@ namespace GtkSharp { { if (RemoveIfNotAlive ()) return; object[] _args = new object[4]; - _args[0] = (Gtk.Clipboard) GLib.Object.GetObject(clipboard); + _args[0] = (Gtk.Clipboard) GLib.Object.GetObject(clipboard, false); if (_args[0] == null) _args[0] = new Gtk.Clipboard(clipboard); _args[1] = selection_data; diff --git a/gtk/Layout.custom b/gtk/Layout.custom index a3b2d4d58..15e0328c4 100644 --- a/gtk/Layout.custom +++ b/gtk/Layout.custom @@ -17,11 +17,10 @@ public Gdk.Window BinWindow { IntPtr raw = gtksharp_gtk_layout_get_bin_window (Handle); if (raw != (IntPtr) 0) { - Gdk.Window ret = (Gdk.Window) GLib.Object.GetObject (raw); - ret.Ref (); + Gdk.Window ret = (Gdk.Window) GLib.Object.GetObject (raw, false); return ret; } return null; } -} \ No newline at end of file +} diff --git a/gtk/Object.custom b/gtk/Object.custom index c98808c47..153fa6d1d 100755 --- a/gtk/Object.custom +++ b/gtk/Object.custom @@ -9,14 +9,17 @@ [DllImport("gtksharpglue")] private static extern bool gtksharp_object_is_floating (IntPtr raw); + [DllImport("libgobject-2.0-0.dll")] + private static extern void g_object_ref (IntPtr raw); + protected override IntPtr Raw { get { return base.Raw; } set { base.Raw = value; - if (!needs_ref && gtksharp_object_is_floating (value)) { - Ref (); + if (gtksharp_object_is_floating (value)) { + g_object_ref (value); Sink (); } // System.Diagnostics.Debug.WriteLine ("Gtk.Object:set_Raw: object type is: " + (this as GLib.Object).GType.Name + " refcount now: " + RefCount + " needs_ref: " + needs_ref); diff --git a/gtk/Paned.custom b/gtk/Paned.custom index 9c2b5fc6a..705441ed1 100644 --- a/gtk/Paned.custom +++ b/gtk/Paned.custom @@ -12,12 +12,12 @@ static extern IntPtr gtksharp_paned_get_child1 (IntPtr i); public Gtk.Widget Child1 { - get { return new Widget (gtksharp_paned_get_child1 (this.Handle)); } + get { return GLib.Object.GetObject (gtksharp_paned_get_child1 (this.Handle), false) as Widget; } } [DllImport ("gtksharpglue")] static extern IntPtr gtksharp_paned_get_child2 (IntPtr i); public Gtk.Widget Child2 { - get { return new Widget (gtksharp_paned_get_child2 (this.Handle)); } + get { return GLib.Object.GetObject (gtksharp_paned_get_child2 (this.Handle), false) as Widget; } } diff --git a/gtk/Style.custom b/gtk/Style.custom index 438123fd5..359dc0ff1 100644 --- a/gtk/Style.custom +++ b/gtk/Style.custom @@ -12,7 +12,7 @@ static Gdk.GC EnsureGC (IntPtr raw) { if (raw == IntPtr.Zero) return null; - Gdk.GC ret = (Gdk.GC) GLib.Object.GetObject (raw); + Gdk.GC ret = (Gdk.GC) GLib.Object.GetObject (raw, false); if (ret == null) ret = new Gdk.GC (raw); return ret; diff --git a/gtk/TreeSelection.custom b/gtk/TreeSelection.custom index d0b32e6cb..0106ed9fc 100644 --- a/gtk/TreeSelection.custom +++ b/gtk/TreeSelection.custom @@ -17,6 +17,6 @@ IntPtr handle = (IntPtr) 0; bool raw_ret = gtk_tree_selection_get_selected(Handle, out handle, ref iter); bool ret = raw_ret; - model = (Gtk.TreeModel)GLib.Object.GetObject (handle); + model = (Gtk.TreeModel)GLib.Object.GetObject (handle, false); return ret; } diff --git a/gtk/TreeView.custom b/gtk/TreeView.custom index a946be5c6..03daa5497 100644 --- a/gtk/TreeView.custom +++ b/gtk/TreeView.custom @@ -22,7 +22,7 @@ public Gtk.TreeModel Model { get { IntPtr raw_ret = gtk_tree_view_get_model (Handle); - Gtk.TreeModel ret = (Gtk.TreeModel) GLib.Object.GetObject (raw_ret); + Gtk.TreeModel ret = (Gtk.TreeModel) GLib.Object.GetObject (raw_ret, false); return ret; } diff --git a/gtk/Widget.custom b/gtk/Widget.custom index 35139aa19..f0e1c0d0a 100644 --- a/gtk/Widget.custom +++ b/gtk/Widget.custom @@ -23,8 +23,7 @@ public Gdk.Window GdkWindow { IntPtr raw_ret = gtksharp_gtk_widget_get_window (Handle); if (raw_ret != (IntPtr) 0){ - Gdk.Window ret = (Gdk.Window) GLib.Object.GetObject(raw_ret); - ret.Ref (); + Gdk.Window ret = (Gdk.Window) GLib.Object.GetObject(raw_ret, false); return ret; } return null;