Как передать несколько переменных в виде данных с помощью сигналов gtk
У меня есть небольшая программа, в которой функция обратного вызова сигнала gtk требует 2 или 3 переменных.
Я не хочу делать эти глобальные переменные (вся цель проекта должна быть аккуратной и аккуратной), и я не хочу создавать целую структуру, чтобы я мог отправлять виджет и скомпилированное регулярное выражение функция.
Насколько я видел, g_signal_connect
допускает только одну переменную данных.
Может ли самый эффективный способ сделать это, возможно, быть массивом указателей void для двух объектов? Что-то вроде этого?
void * data[2];
data[0] = widget;
data[1] = compiledregex;
g_signal_connect(save,"clicked",G_CALLBACK(callbackfunction),data);
Ответы
Ответ 1
Конечно, вы можете использовать массивы указателей void, но если вы хотите передавать значения с разными типами (особенно значения, тип которых длиннее sizeof(void *)
), вы не можете использовать массивы. Для этого вы почти наверняка захотите обернуть их в структуру и передать адрес структуры в качестве параметра данных.
Пример:
struct my_struct *data = malloc(sizeof(*data));
data->field_one = value_one;
data->field_two = value_two; /* etc. */
g_signal_connect(save, "clicked", callback, data);
Конечно, не забудьте free(data)
в функции обратного вызова (при условии, что он используется для одного использования).
Изменить: как вам нужен пример с void **, вот вы (это уродливо, и я не рекомендую вам использовать это - либо потому, что выделение одноэлементного массива для примитивных типов тратит впустую вашу съемку или из-за того, что литье не указателя на void * является плохой практикой...):
void **data = malloc(sizeof(data[0]) * n_elements);
type1 *element1_ptr = malloc(sizeof(first_item));
*element1_ptr = first_item;
data[0] = element1_ptr;
/* etc. */
Чтобы освободить их:
int i;
for (i = 0; i < n_elements; i++)
free(data[i]);
free(data);
Ответ 2
Вы можете использовать g_object_set_data() и g_object_get_data(). Сначала задайте данные:
g_object_set_data(G_OBJECT(my_edit), "my_label", my_label);
g_object_set_data(G_OBJECT(my_edit), "age", GINT_TO_POINTER(age));
а в обратном вызове вы можете получить такие данные:
gint age = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "age"));
GtkWidget *my_label = g_object_get_data(G_OBJECT(widget), "my_label");
Ответ 3
Развернув ответ H2CO3, вы также можете установить данные (и я настоятельно рекомендую использовать структуру, кстати), чтобы автоматически освободиться при отключении обработчика сигнала:
g_signal_connect_data(save, "clicked", callback, data, (GClosureNotify)free, 0);