Re: Gnome canvas problem on Ubuntu




On Dec 2, 2005, at 3:57 PM, Grant McLean wrote:

I don't seem to be able to use bezier path objects with the packaged
version of Gnome2::Canvas in Ubuntu 5.10 ('Breezy'). For example, this
test script should display a blue semi-circle:
[...]
Instead, the following errors are output and nothing is displayed on the
canvas:

GLib-GObject-CRITICAL **: g_boxed_type_register_static: assertion
`g_type_from_name (name) == 0' failed at ./beziertest.pl line 19.

That error means that the type name has already been registered. There's an interesting forensic tale here that illustrates a poor choice on my part for how to work around a missing boxed wrapper in older versions of libgnomecanvas, but i'll get that that in a minute.

The problem is that you're using a build of Gnome2::Canvas compiled against an older version of libgnomecanvas with a new version of libgnomecanvas, and the workaround for the older versions is breaking.

Simply recompiling Gnome2::Canvas against the new libgnomecanvas will give you a working binding. This would be an easy fix for the Ubuntu packagers, and is really The Right Solution.

Please bug your neighborhood Ubuntu gtk2-perl package maintainer to rebuild the package.


What's wrong, you ask?

libgnomecanvas did not used to provide a boxed type wrapper for GnomeCanvasPathDef, but we needed this wrapper to make the bindings work sanely. Since libgnomecanvas development is slow (in maintenance mode), i added a workaround. At the time it seemed nice: if GNOME_TYPE_CANVAS_PATH_DEF is defined, use it as is, otherwise, provide a fallback. That way, when the upstream library starts to provide it, we'll just use it. Where this falls down is the situation you're in --- an upstream upgrade without a recompile. Since the workaround was done at compile time, the bindings don't know about the new definition of the GNOME_TYPE_CANVAS_PATH_DEF macro, and continue to call the old workaround fallback function, which registers a type with the same name as the upstream one. And there's where the problem is. When libgnomecanvas tries to register the type, it finds the name is already in use, and barfs.

GnomeCanvasPathDef.xs contains this comment:

/*
* if/when libgnomecanvas provides a boxed wrapper for GnomeCanvasPathDef,
* we'll have to put these two functions behind version guards.
*/

but in retrospect, this isn't really enough.

/me digs for a little while...

In May of this year, Kjartan Maraas applied a patch that apparently i added to bugzilla in January of '04, on a bug i opened in July of '03.
http://bugzilla.gnome.org/show_bug.cgi?id=116734

*cough*  I guess i'd better make good on that.  :-)

The first release with this patch is 2.12.0, so that means we need to have a new release of Gnome2::Canvas that plays nicely.



One interesting technical challenge here is how to figure out what version of libgnomecanvas we're using at runtime. glib and gtk+ provide runtime version information, but from what i gather this has been deemed more trouble than it's worth and no other gnome libraries do that. So, we'll have to do some form of evil dlsym() trick... e.g.

   #ifndef GNOME_TYPE_CANVAS_PATH_DEF
# define GNOME_TYPE_CANVAS_PATH_DEF gnomecanvasperl_canvas_path_def_get_type()
   # define GNOMECANVASPERL_PATH_DEF_WORKAROUND
   #endif

#ifdef GNOMECANVASPERL_PATH_DEF_WORKAROUND

#include <gmodule.h>

static GnomeCanvasPathDef *
path_def_boxed_copy (GnomeCanvasPathDef * path_def)
{
        if (path_def)
                gnome_canvas_path_def_ref (path_def);
        return path_def;
}

GType
gnomecanvasperl_canvas_path_def_get_type (void)
{
        static GType id = 0;
        if (!id) {
                GModule * module;
                GType (*get_type) (void);

                module = g_module_open ("libgnomecanvas-2", G_MODULE_BIND_LAZY);
                g_printerr ("%s\n\tmodule = %p\n", __FUNCTION__, module);
                if (module &&
                    g_module_symbol (module,
                                     "gnome_canvas_path_def_get_type",
                                     &get_type)) {
                        id = get_type ();
                        g_printerr ("\tget_type = %p\n", get_type);
                        g_module_close (module);
                } else
                        id = g_boxed_type_register_static
                                ("GnomeCanvasPathDef",
                                 (GBoxedCopyFunc) path_def_boxed_copy,
                                 (GBoxedFreeFunc) gnome_canvas_path_def_unref);
                g_printerr ("\tid = %d\n", id);
        }
        return id;
}

#endif



ugh. That works on linux, but i don't know how portable it is or how reliable it is. Anybody have a better idea?


--
Our enemies are innovative and resourceful, and so are we. They never stop thinking about new ways to harm our country and our people, and neither do we.
  -- President George W. Bush




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