2009-10-12 4 views
3

Я пытаюсь создать и излучать сигнал GTK:создавать и излучать Gtk сигнал

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); 

Вот мой код, который выдает сигнал:

gtk_signal_emit_by_name(referenceToMyWindow, "child-finished"); 

И вот мой код, который обрабатывает сигнал:

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

Когда я запускаю код, я получаю следующее сообщение об ошибке:

GLib-GObject-CRITICAL **: g _closure_ invoke: assertion `closure->marshal || closure->meta_marshal' failed

Я знаю, что есть что-то делать с пропусканием маршаллер функции g_signal_new, но я не знаю, что такое маршаллер, я не могу понять the documentation и примеры в Интернете очень мало, и далеко друг от друга. Как объявить и подключить собственный сигнал?

ответ

3

Библиотека GObject предоставляет некоторые builtin marshallers, так что ваш код должен вероятно быть:

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); 

или, если вы хотите проверки типов:

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); 

Параметры обработчика сигнала должен быть present (подразумевается сам объект), поэтому обязательно указывайте указатель (как в первом примере) или тип в штучной упаковке (как во втором примере).

Если у вас нет встроенного маршаллера, вы можете использовать служебную программу glib-genmarshal или напрямую ее код (это довольно тривиально, просто проверьте выход glib-genmarshal).

+0

Просто исправление сказанного выше: типы GBoxed не имеют проверки типов, они являются только обертками для C-структур без информации типа. Реальная разница между G_TYPE_POINTER и G_TYPE_BOXED заключается в том, что в последнем используется _copy_ структуры GdkEvent. Если событие не изменено, это не имеет никакого значения, но если вам нужно его изменить, используйте G_TYPE_POINTER. – ntd

Смежные вопросы