Как создавать и использовать сигналы

Пример использования сигналов
Как обеспечить большую гибкость для пользователей?
Как большинство людей делают одно и тоже с меньшим количеством кода
Как пользователи могут злоупотреблять сигналами (и почему некоторые думают что это хорошо)

Система сигналов которая была создана в GType довольно сложная и гибкая: она позволяет пользователям подключать в основном цикле любое количество callback-функций (реализовано в любом языке для которого есть привязка) [16] к любому сигналу и останавливать эмиссию любого сигнала в любом состоянии. Эта гибкость делает возможным использование GSignal намного шире чем простое издание событий которые могут быть получены многочисленными клиентами.

Пример использования сигналов

Самое основное использование сигналов это осуществление простого уведомления о произошедшем событии: например, если вы имеете объект MamanFile, и если этот объект имеет написанный метод, можно получать уведомление каждый раз когда кто-нибудь использует этот метод. Код ниже показывает как пользователь может подключить callback-функцию к созданному сигналу. Полный код этого примера расположен в sample/signal/maman-file.{h|c} и в sample/signal/test.c

file = g_object_new (MAMAN_FILE_TYPE, NULL); g_signal_connect (G_OBJECT (file), "write", (GCallback)write_event, NULL); maman_file_write (file, buffer, 50);

Сигнал MamanFile регистрируется в функции class_init:

klass->write_signal_id = g_signal_newv ("write", G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL /* class closure */, NULL /* accumulator */, NULL /* accu_data */, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE /* return_type */, 0 /* n_params */, NULL /* param_types */);

а издаётся сигнал в maman_file_write:

void maman_file_write (MamanFile *self, guint8 *buffer, guint32 size) { /* Сначала записываем данные. */ /* Затем, сообщаем пользователю о записанных данных. */ g_signal_emit (self, MAMAN_FILE_GET_CLASS (self)->write_signal_id, 0 /* details */, NULL); }

Как показано выше, вы можете безопасно установить детальный параметр в ноль если вы не знаете для чего его использовать. Обсуждение того где он может использоваться, смотрите “The detail argument”

Сигнатура обработчика сигнала в примере выше определена как g_cclosure_marshal_VOID__VOID. Это название следует простому соглашению - кодировать параметр функции и тип возвращаемого значения в имени функции. Определено что, значение перед двойным подчёркиванием это тип возвращаемого значения, в то время как значение(я) после двойного подчёркивания обозначает тип параметров. Заголовок gobject/gmarshal.h определяет основной набор необходимых замыканий которые можно использовать.



[16] python callback-функции могут быть подключены к любому сигналу в любом C-подобном GObject.