g_signal_connect_data instead of g_signal_connect_object, because GHashTable is not a GObject

I just blew two hours figuring out that a GLib GHashTable is not a descendent of GObject. Duh!

GLib's data types are more primitive than GObject. Being a n00b, I just didn't grasp that GObject is the root of an signaling and function/closure system, not all objects.

I was supposed to use g_signal_connect_data instead of g_signal_connect_object. Ooops. g_signal_connect_object seems to be used when passing around references to gtk widgets.

An interesting thing is that it looks like we should be using g_signal_connect_data instead of g_signal_connect. The former uses GClosure to wrap the data, and make sure it persists. g_signal_connect doesn't do that, so it's up to the programmer to make sure that the data is available; that means saving it on the heap, or into a global array.

(GClosure's implementation seems to be an array of closure objects, so it's ultimately in some global data structure. It's just easier to use the closures, because the system will manage it.)

The tutorials out there, both the GTK2 and GTK3 tutorials, don't use g_signal_connnect_data or the corresponding _object function.

This is a test case, and harness.

#include 
#include 

void cb( GtkButton *button, GHashTable *hash );

int main( int argc, char *argv[] )
{
    GString *s;
    GString *value;
    GHashTable *command;
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box;

    g_type_init();
    gtk_init( &argc, &argv );
    
    command = g_hash_table_new( g_direct_hash, g_direct_equal );

    s = g_string_new("hello");
    g_hash_table_insert( command, "test", s );
    value = g_hash_table_lookup( command, "test" );
    printf("%s\n", value->str);
    
    window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
    button = gtk_button_new_with_label( "test" );
    g_signal_connect_data( button, "clicked",
                             G_CALLBACK(cb),
                             command,
                             NULL,
                             0 );
    box = gtk_hbox_new( TRUE, 5 );
    gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 5 );
    gtk_widget_show( GTK_WIDGET(box) );    
    gtk_widget_show( GTK_WIDGET(button) );    
    gtk_container_add( GTK_CONTAINER (window), GTK_WIDGET(box) );
    gtk_widget_show( window );
    gtk_main();
}

void cb( GtkButton *button, GHashTable *hash )
{
    GString *value;
    value = g_hash_table_lookup( hash, "test" );
    printf("in cb %s\n", value->str);    
}