tags:

views:

773

answers:

1

I am trying to create and emit a GTK signal:

g_signal_new("child-finished",
    G_TYPE_OBJECT,
    G_SIGNAL_RUN_FIRST,
    0,
    NULL, NULL,
    NULL,           // *** I think this is where I need to change it
    G_TYPE_NONE, 0);
g_signal_connect(G_OBJECT(myWindow), "child-finished", G_CALLBACK(MyCallback), NULL);

Here is my code that emits the signal:

gtk_signal_emit_by_name(referenceToMyWindow, "child-finished");

And here is my code that handles the signal:

void MyCallback(GtkWidget *w, GdkEvent *e)
{
    // handler code here
}

When I run the code I get the following error:

GLib-GObject-CRITICAL **: g_closure_invoke: assertion `closure->marshal || closure->meta_marshal' failed

I know it has something to do with passing a marshaller to the g_signal_new function, but I don't know what a marshaller is, I can't understand the documentation, and the examples online are few and far between. How do I declare and connect my own signal?

+1  A: 

The GObject library provides some builtin marshallers, so your code should probably be:

g_signal_new("child-finished",
             G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST,
             0, NULL, NULL,
             g_cclosure_marshal_VOID__POINTER,
             G_TYPE_NONE, 1, G_TYPE_POINTER);

or, if you want type checking:

g_signal_new("child-finished",
             G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST,
             0, NULL, NULL,
             g_cclosure_marshal_VOID__BOXED,
             G_TYPE_NONE, 1, GDK_TYPE_EVENT);

The parameters of the signal handler must be present (the object itsself is implied), so be sure to specify a pointer (as in the first example) or a boxed type (as in the second example).

If the marshaller you need is not present in the builtins ones, you could use the glib-genmarshal utility or directly code it by yourself (it is quite trivial, just checkout the output of glib-genmarshal).

ntd
Just a correction of what said above: GBoxed types do not have type checking, they are only wrappers for C structs with no type information. The real difference between G_TYPE_POINTER vs G_TYPE_BOXED is that in the latter a _copy_ of the GdkEvent structure is used. If event is not modified this does not make any difference but if you need to modify it, use G_TYPE_POINTER.
ntd