GTK +:将数据传递给call_back函数

时间:2011-11-15 23:45:22

标签: c gtk

我正在构建一个执行以下操作的GTK程序:用户单击一个按钮,它从服务器检索信息,然后创建用户可以单击的新按钮。我在main中有一个信号,在call_back中我有多个信号(对于每个创建的按钮)。

我想将数据传递给这个新按钮,但在这里变得icky。如果我在第一个按钮内创建了一个struct,我将在生成的按钮中崩溃,因为该结构是在堆栈上本地定义的,因此它会被删除。

我无法创建全局变量,因为每个创建的按钮都需要不同的值。当我的初始按钮(回调方法)被调用时,我基本上想要传递一个包含多个字段的结构,但每个结构都不同。

我能想到的唯一方法是在堆上分配它,但知道何时释放它会变得有点开销。

有没有一个好方法可以解决这个问题,或者我是否通过让信号处理程序创建一个新的信号处理程序来为GTK做出错误的设计选择?

非常感谢。

编辑:

我还在崩溃,我很困惑为什么。

这是主按钮的代码:

struct buttonData* data = (struct buttonData*) malloc(sizeof(struct buttonData));
data->IP = strdup(newDevice.IP.c_str()); // Added strdup
data->port = atoi(newDevice.port.c_str());
g_signal_connect(G_OBJECT(deviceButton), "button_press_event", G_CALLBACK(showDeviceAndConnect), (gpointer) data);

生成按钮的代码:

static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data) {
    struct buttonData* toConnect = (struct buttonData *) data;
    fprintf(stderr, "IP: %s, PORT: %d\n", toConnect->IP, toConnect->port); //SIGSEGV
}

我不确定为什么。任何帮助都将非常感激。

2 个答案:

答案 0 :(得分:2)

崩溃的原因是回调的签名。 "button-press-event"期望回调带有签名gboolean foo(GtkWidget* , GdkEvent*, gpointer)。当你的回调具有void foo (GtkWidget * , gpointer )的签名时,你在回调函数中获得的第二个参数不是在注册回调时使用的gpointer数据而是GdkEvent指针。因此,当您取消引用GdkEvent指针(将其视为已传递的数据)时,您将看到崩溃。因此,要解决此问题,请将static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data)更改为static void showDeviceAndConnect(GtkWidget * deviceButton, GdkEvent *ev, gpointer data) 或者,由于您只使用showDeviceAndConnect函数中的数据,因此您可以使用g_signal_connect_swapped将数据作为第一个参数传递;因此,如果您使用g_signal_connect_swapped,则您的功能static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data)可以是static void showDeviceAndConnect(gpointer data) 希望这有帮助!

答案 1 :(得分:1)

  

我能想到的唯一方法是在堆上分配它,但知道何时释放它会变得有点开销。

这是做到这一点的方法。在堆上分配结构并将指针作为回调数据传递给它。请注意,即使它不适用于您,因为您正在动态生成这些按钮,因此使用全局变量作为解决方案的选择不是很好。