Re: Problems with GHashTable in signal handler




On Oct 25, 2009, at 8:55 AM, Jörn Reder wrote:

Hi,

I try to use the "create-plugin-widget" signal of Gtk2::WebKit::WebView, which passes a GHashTable to the callback. Here it's signature from the
docs:

 GtkWidget* user_function (WebKitWebView *web_view,
                           gchar         *mime_type,
                           gchar         *uri,
                           GHashTable    *param,
gpointer user_data) : Run Last / Action

(from http://webkitgtk.org/reference/webkitgtk-WebKitWebView.html#WebKitWebView-create-plugin-widget )

Perl dies with this error message when my signal handler is called:

 GType GHashTable (146176672) is not registered with gperl

Since signal handling is completely covered on Glib level I don't think
this problem is related to Gtk2::WebKit. The Glib perldoc says
GHashTable is bound to the native Perl hash datatype. I grep'ed the
sources of Glib and Gtk2 to find any examples of passing GHashTables to
Perl - with no luck.

Any help on this is appreciated ;)


Actually, the docs say "The GLib types GList (a doubly-linked list), GSList (singly-linked list), GHashTable, GArray, etc have all been replaced by native Perl datatypes." That is, "replace by", not "bound to." GHashTable is not really bindable, because it is a generic mapping of arbitrary pointer to arbitrary pointer; you must know something about what is in it in order to use it, and we can't create a generic wrapper for that. Therefore, for each function that passes a hash table, we map that by hand to a perl hash.

However, it's not actually very common for the gnome APIs to pass GHashTables around -- they're normally used for implementation. In fact, i can't really think of where we've had to do this...


libgobject started registering a GType for GHashTable in 2.10, to make it possible to say "this signal argument is a hash table" instead of "this signal argument is a pointer". However, as the gobject- introspection guys pointed out, this isn't terribly useful; you need to know more information, like "this object is a hash table whose keys are strings and whose values are gobjects". We don't have that at a generic level.


So the only real option that you have is to create a custom marshaller for this signal, implemented in Gtk2::WebKit::WebView. This marshaller would be used only for this signal, where we know that the hash table is supposed to be a map of strings to strings. You'd do something like call g_hash_table_foreach() to push all the keys and values in the hash table into a new hash, and pass a reference to that new hash to perl in place of the hash table. (The closer you stick to the C api, the fewer problems people will have here.) If you're supposed to allow the callback to modify the hash, then you'll have to push those changes back the other way when the callback returns.

Read gperl_marshal.h for a template and helpers. There are a few examples of custom marshallers in Gtk2, nearly all used for arguments that are unfriendly to non-C languages (e.g. write-through integer parameters, C arrays, and G_TYPE_POINTER args that you're supposed to cast to something else). Search Gtk2 for gperl_signal_set_marshaller_for and follow where that takes you.

From Glib::xsapi:

void gperl_signal_set_marshaller_for (GType instance_type, char * detailed_signal, GClosureMarshal marshaller)

      You need this function only in rare cases, usually as workarounds
for bad signal parameter types or to implement writable arguments. Use the given marshaller to marshal all handlers for detailed_sig-
       nal on instance_type.  "gperl_signal_connect" will look for mar-
       shallers registered here, and apply them to the GPerlClosure it
       creates for the given callback being connected.

       Use the helper macros in gperl_marshal.h to help write your mar-
       shaller function.  That header, which is installed with the Glib
module but not #included through gperl.h, includes commentary and examples which you should follow closely to avoid nasty bugs. Use
       the Source, Luke.

WARNING: Bend over backwards and turn your head around 720 degrees before attempting to write a GPerlClosure marshaller without using the macros in gperl_marshal.h. If you absolutely cannot use those
       macros, be certain to understand what those macros do so you can
       get the semantics correct, and keep your code synchronized with
       them, or you may miss very important bugfixes.





--
Me:  What's that in your mouth?
Zella:  *swallows laboriously*  Nothing.
Me:  What did you just swallow?
Zella:  A booger.
Me:  Baby girl, don't eat boogers.  That's gross.
Zella:  But it was in my nose.




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