如何将 pointers/arrays 作为参数传递给 GTK 回调函数?
How do you pass pointers/arrays as parameters to a GTK callback function?
我想将整数列表 numbers
传递给回调函数 printer
,按下按钮时它将打印 numbers
的内容。 this 论坛帖子中的最后一个 post 建议我这样做:
#include <gtk/gtk.h>
static void printer(GtkButton *button, gpointer user_data)
{
int *array = user_data;
g_print("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
static void activate(GtkApplication *app, gpointer user_data)
{
GtkWidget *win;
GtkWidget *box;
GtkWidget *button;
// initialize numbers
int numbers[5] = {2, 3, 5, 7, 11};
// window
win = gtk_application_window_new(GTK_APPLICATION(app));
gtk_window_set_title(GTK_WINDOW(win), "Printer");
gtk_window_set_default_size(GTK_WINDOW(win), 80, 80);
// box
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child(GTK_WINDOW(win), box);
// button
button = gtk_button_new_with_label("Test");
g_signal_connect(button, "clicked", G_CALLBACK(printer), (gpointer) numbers);
gtk_box_append(GTK_BOX(box), button);
gtk_window_present(GTK_WINDOW(win));
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("com.example.printer", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
然而,当我尝试执行这个时,程序输出:
0 0 0 32583 0
如果回调函数在打印之前修改了数组的内容,那么打印的结果将是正确的:
static void printer(GtkButton *button, gpointer user_data)
{
int *array = user_data;
array[0] = 3;
array[1] = 2;
array[2] = 1;
array[3] = 0;
array[4] = -1;
g_print("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
这会按预期输出 3 2 1 0 -1
。
我不确定为什么 array[x]
在这两种情况下都不一样。这是将数组传递给回调函数的推荐方法吗?为什么 array[x]
return 两种情况下的值不同?
您要传递给回调函数的地址数组是 local 到 activate
函数。因此,当(稍后)实际进行回调时,activate
函数已完成并且指向 (numbers
) 的数据缓冲区已超出范围。因此,您有未定义的行为。
在你的情况下,回调例程仍然可以访问该内存(但不要依赖于此)但是你在初始化中放置在那里的数据已被覆盖(被什么代码扇区和多少次,是几乎不可能分辨,因为内存很可能在堆栈的某个地方)——因此你看到的是垃圾值。但是,当您在回调函数 (printer
) 中提供 new 值时,这些值会正确显示(但从技术上讲,您仍然有未定义的行为,因为内存指向来自 user_data
可能 不再可用)。
解决此问题的一种方法是创建 numbers
数组 static
,以便在 activate
函数完成时保留内存:
static void activate(GtkApplication *app, gpointer user_data)
{
GtkWidget *win;
GtkWidget *box;
GtkWidget *button;
// initialize numbers
static int numbers[5] = {2, 3, 5, 7, 11}; // Make "static" to preserve after call
//...
其他选项是:(a) 使 numbers
数组成为一个全局变量(不太好,而且常常不受欢迎); (b) 使用 malloc
为数组动态分配内存(在堆上)(但是当你用完它时你需要释放该内存)。
我想将整数列表 numbers
传递给回调函数 printer
,按下按钮时它将打印 numbers
的内容。 this 论坛帖子中的最后一个 post 建议我这样做:
#include <gtk/gtk.h>
static void printer(GtkButton *button, gpointer user_data)
{
int *array = user_data;
g_print("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
static void activate(GtkApplication *app, gpointer user_data)
{
GtkWidget *win;
GtkWidget *box;
GtkWidget *button;
// initialize numbers
int numbers[5] = {2, 3, 5, 7, 11};
// window
win = gtk_application_window_new(GTK_APPLICATION(app));
gtk_window_set_title(GTK_WINDOW(win), "Printer");
gtk_window_set_default_size(GTK_WINDOW(win), 80, 80);
// box
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child(GTK_WINDOW(win), box);
// button
button = gtk_button_new_with_label("Test");
g_signal_connect(button, "clicked", G_CALLBACK(printer), (gpointer) numbers);
gtk_box_append(GTK_BOX(box), button);
gtk_window_present(GTK_WINDOW(win));
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("com.example.printer", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
然而,当我尝试执行这个时,程序输出:
0 0 0 32583 0
如果回调函数在打印之前修改了数组的内容,那么打印的结果将是正确的:
static void printer(GtkButton *button, gpointer user_data)
{
int *array = user_data;
array[0] = 3;
array[1] = 2;
array[2] = 1;
array[3] = 0;
array[4] = -1;
g_print("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
这会按预期输出 3 2 1 0 -1
。
我不确定为什么 array[x]
在这两种情况下都不一样。这是将数组传递给回调函数的推荐方法吗?为什么 array[x]
return 两种情况下的值不同?
您要传递给回调函数的地址数组是 local 到 activate
函数。因此,当(稍后)实际进行回调时,activate
函数已完成并且指向 (numbers
) 的数据缓冲区已超出范围。因此,您有未定义的行为。
在你的情况下,回调例程仍然可以访问该内存(但不要依赖于此)但是你在初始化中放置在那里的数据已被覆盖(被什么代码扇区和多少次,是几乎不可能分辨,因为内存很可能在堆栈的某个地方)——因此你看到的是垃圾值。但是,当您在回调函数 (printer
) 中提供 new 值时,这些值会正确显示(但从技术上讲,您仍然有未定义的行为,因为内存指向来自 user_data
可能 不再可用)。
解决此问题的一种方法是创建 numbers
数组 static
,以便在 activate
函数完成时保留内存:
static void activate(GtkApplication *app, gpointer user_data)
{
GtkWidget *win;
GtkWidget *box;
GtkWidget *button;
// initialize numbers
static int numbers[5] = {2, 3, 5, 7, 11}; // Make "static" to preserve after call
//...
其他选项是:(a) 使 numbers
数组成为一个全局变量(不太好,而且常常不受欢迎); (b) 使用 malloc
为数组动态分配内存(在堆上)(但是当你用完它时你需要释放该内存)。