11

我有一个小程序,其中 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);
4

3 回答 3

9

当然你可以使用 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);
于 2012-08-04T13:11:01.137 回答
6

您可以使用 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");
于 2012-08-08T01:59:01.263 回答
3

扩展 H2CO3 的答案,您还可以将数据(顺便说一下,我强烈建议使用结构)设置为在信号处理程序断开连接时自动释放:

g_signal_connect_data(save, "clicked", callback, data, (GClosureNotify)free, 0);
于 2012-08-08T21:26:02.377 回答