Есть ли способ игнорировать сигналы подписи? - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь подключить некоторые виджеты с одним и тем же обратным вызовом user_function.В некоторых случаях сигнал имеет разные подписи.

Поиском я нашел gtk_signal_connect_full, я думаю.

Мой код, например:

int MyObject::connect()
{
    callback_object ....

    // Create the callback
    int ret = g_signal_connect(instance, "clicked", G_CALLBACK (connect_callback), callback_object);
    int ret = g_signal_connect(instance, "button-release-event", G_CALLBACK (connect_callback), callback_object);

    // Return handler id
    return ret;
}

void MyObject::connect_callback(GObject *passedInstance, gpointer param1, gpointer param2)
{
    // Return to st_callback
    struct st_callback *callback_object = (struct st_callback *) param2;
    if(sizeof(param1) == 0) {
        callback_object = (struct st_callback *) param1;
    }

}

Можно ли "абстрагировать" user_functionкак это?и если я могу, Как получить дополнительные параметры, такие как GdkEvent или GdkEventButton, или gchar, ...

EDIT - этот вопрос является проблемой GTK +, потому что в первом g_signal_connect param1 - моя структура.Я в порядке, я знаю мою структуру, чтобы отбросить.Во втором g_signal_connect param1 является кнопкой GdkEventButton.Это тоже нормально, потому что я знаю, что это GdkEventButton для отбрасывания.НО, как это сделать, если я не знаю, что param1 является моей структурой, если это GdkEvent, GdkEventButton, gchar или все другие возможности синусных сигнатур?

РЕДАКТИРОВАТЬ 2 - я нашел эту информацию в Closures doc

Закрытия позволяют вызываемому объекту получать типы параметров обратного вызова, что означает, что языковые привязки не должны писать отдельный клей для каждого типа обратного вызова.

Это замечательно для того, что я ищу, но я не нашел ничего более, что оно

РЕДАКТИРОВАТЬ 3

С ebassi ideia о, g_signal_query - это то, что мне нужно,Я делаю это для резюме:

1 - запрашиваем параметры сигнала с помощью g_signal_query, устанавливаем в мою структуру для передачи с обратным вызовом user_data 2 - соединяемся с g_cclosure_new_swap и g_signal_connect_closure, этот набор gpointer user_data устанавливается как первый параметр 3 - создается обратный вызовкак это: connect_callback(gpointer user_data, ...), со списком переменных параметров 4 - внутри обратного вызова, вернуть мою структуру с результатом custom + g_signal_query 5 - зациклить в param_types GSignalQuery, проверяя каждый фундаментальный тип 6 - получить va_arg с правильным типом

Полный код для обратного вызова

    // Create gpoint param
    struct st_callback *callback_object = (struct st_callback *)malloc(sizeof(struct st_callback));
    memset(callback_object, 0, sizeof(struct st_callback));

    callback_object->callback_name = callback_name;
    callback_object->callback_params = callback_params;

    // Get params of signal
    GSignalQuery signal_info;
    g_signal_query(g_signal_lookup (callback_signal, G_OBJECT_TYPE (instance)), &signal_info);

    // Save 
    callback_object->signal_id = signal_info.signal_id;
    callback_object->signal_name = signal_info.signal_name;
    callback_object->itype = signal_info.itype;
    callback_object->signal_flags = signal_info.signal_flags;
    callback_object->return_type = signal_info.return_type;
    callback_object->n_params = signal_info.n_params;
    callback_object->param_types = signal_info.param_types;

    GClosure  *closure;
    closure = g_cclosure_new_swap (G_CALLBACK (connect_callback), callback_object, NULL);
    int ret = g_signal_connect_closure (instance, callback_event, closure, TRUE);

И обратный вызов

static bool connect_callback(gpointer user_data, ...)
{
    // Return to st_callback
    struct st_callback *callback_object = (struct st_callback *) user_data;

    // get parameters count
    int param_count = callback_object->n_params;
    va_list ap;
    va_start(ap, param_count);

    // loop paramters
    for (int i=0; i<param_count; i++) {

        switch (G_TYPE_FUNDAMENTAL(callback_object->param_types[i])) {
            case G_TYPE_CHAR:

                break;
            case G_TYPE_UCHAR:

                break;
            case G_TYPE_STRING:
            {
                char *path = va_arg(ap, char *);
                break;
            }
            case G_TYPE_OBJECT:

                break;
            case G_TYPE_POINTER:

                break;
            case G_TYPE_INTERFACE: 

                break;
            case G_TYPE_PARAM:

                break;
            case G_TYPE_BOXED:
            {
                // Example, try to cast correct boxed
                GdkEvent *e = va_arg(ap, GdkEvent *);

                break;
            }
        }
    }

    va_end(ap);
}

Требуется исправить возврат и приведение в штучной упаковке, но с этим я могу нормально работать

1 Ответ

2 голосов
/ 13 мая 2019

Вы не должны использовать одну и ту же функцию для разных типов обратных вызовов.Некоторые обратные вызовы принимают разные параметры, другие имеют разные возвращаемые значения - например, в вашем примере clicked ничего не возвращает, тогда как button-press-event возвращает логическое значение.

Если у вас есть общий код, который долженбыть выполненным в различных обработчиках сигналов, написать функцию и затем вызвать ее из различных обработчиков.

...