我正在构建一个执行以下操作的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
}
我不确定为什么。任何帮助都将非常感激。
答案 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)
我能想到的唯一方法是在堆上分配它,但知道何时释放它会变得有点开销。
这是做到这一点的方法。在堆上分配结构并将指针作为回调数据传递给它。请注意,即使它不适用于您,因为您正在动态生成这些按钮,因此使用全局变量作为解决方案的选择不是很好。