Re: More wrapping fun





On 10/3/06, Murray Cumming <murrayc murrayc com> wrote:
On Mon, 2006-10-02 at 20:52 -0500, Paul Davis wrote:
> Howdy,
>
> I've managed to narrow down this problem.  And I'm at a loss for
> words.
>
> Basically, after the model gets set on a view, the view gets notified
> when any Item is created in the model so that the View can emit an
> item_view_created signal.
>
> Guess what. It looks like when the signal gets emitted, it finishes
> instantiating the object for the cast in the signal handler.  So, by
> the time that things return to my constructor in the call to create(),
> the object has been fully instantiated.

So a second wrap() should just return the existing object. I doubt that
a signal handler is running while wrap() is running.

Its not running *while* wrap is running. What I think is happening is this:

(Prerequiste - The model has been set for a view. Possible need for a signal handler to be attached)

1. A call to GooCanvas::Rect::create( parent, ...) occurs.
2. create() calls new Rect( parent, ...)
3. new Rect() calls goo_canvas_rect_new( parent, ...... )
4. the GooCanvasView (In C land) creates the corresponding ItemView
5. the GooCanvasView emits the item_view_created signal, passing the new GooCanvasItemView and new GooCanvasItem pointers.
6. These two pointers get passed to the on_item_view_created() handler.
7. The GooCanvasItem gets converted to GooCanvas::Item via Glib::wrap().
8. Glib::wrap() causes g_object_set_qdata_full() to be called on the pointer. (Haven't tracked down how or why, but it must.)
9. Evertying rolls back up the stack
10. we finally get back to our constructor. (Remeber the call to create?)
11. the pointer returned from new Rect() gets passed to the super class constructor ItemView::ItemView( GObject* obj )
12. ItemVew::ItemView passes obj to its super class constructor Glib::Object( GObject* obj )
13. Glib::Object ends up calling g_object_get_qdata() which was set in step 8.
14. We print a nice info message.

Therefore.

Rect::Rect(const Glib::RefPtr<Item>& parent, gdouble x, gdouble y, gdouble width, gdouble height )
    :
        ItemSimple( G_OBJECT( goo_canvas_rect_new( parent->gobj(), x, y, width, height, NULL ) ) )
{
}

If the signal handler is active, after G_OBJECT( blah ) returns, the returned object is completely constructed. When ItemSimple( blah ) runs, it attempts to reconstruct the wrapper.

So, I do this:

Glib::RefPtr<Rect>
Rect::create( const Glib::RefPtr<Item>& parent, gdouble x, gdouble y, gdouble width, gdouble height )
{
    return Glib::wrap( GOO_CANVAS_RECT( goo_canvas_rect_new( parent->gobj(), x, y, width, height, NULL ) ), true ) ;
}

No error message. All is good.

I've been looking at this.  Really, there isn't any good reason that this shouldn't be right.

> Now. The question is, how do I make things work despite this?
>
> I've been thinking about removing the GObject* constructor from the
> ItemSimple (the base class) and instead making the wrap method call
> goo_item_"x"_new, and returning a Glib::RefPtr that wraps the return
> of new.

I'm sure that's not necessary. I'd like to look at this, but I don't
have time right now. Can you work around it for now, leaving a TODO
somewhere in the code?

I'll mark it.

--
Murray Cumming
murrayc murrayc com
www.murrayc.com
www.openismus.com




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]