在这种情况下可以避免使用全局变量吗?

时间:2010-08-10 19:47:59

标签: c global-variables gtk

我正在用C编写一个GTK +应用程序(尽管这里的原理是广泛适用的),它包含一个GtkComboBox。 GtkComboBox是另一个函数返回的更大结构的一部分,并打包到主窗口中。

除了从回调函数设置全局变量之外,我没有看到如何获取GtkComboBox中所选内容的值。或者在程序的后面还有某种方式引用GtkComboBox,在声明它的函数之外?

或者我不应该首先在函数内部(main()除外)声明它?

3 个答案:

答案 0 :(得分:5)

我看到你已经接受了答案,但由于GTK有一个优雅的机制来处理所有这些,我觉得不得不写另一个。

gtk_combo_box_new()在内部使用malloc()来分配它返回的指针。 (严格来说,这不是真的,但在这里不要混淆。)所以你的GtkComboBox将一直存活,直到它的父窗口小部件被销毁,或者从它的父窗口小部件中删除,或者直到你手动销毁它(使用gtk_widget_destroy(),而不是free())。因此,小部件存在于后台,但问题是在需要的地方有一个指向它的指针。

通常你会想要操纵组合框以响应信号,因为GTK程序中的大部分工作都是在信号处理程序中完成的。如果它是组合框自己的信号之一,如changed信号,则回调将是这样的函数:

void on_combo_box_changed(GtkComboBox *combo_box, gpointer user_data)

combo_box将是指向组合框的指针。

如果你想操纵组合框以响应另一个小部件的信号,让我们说一个按钮的clicked信号,那么回调将是这样的函数:

void on_button_clicked(GtkButton *button, gpointer user_data)

如您所见,此处没有指向组合框的指针。这是user_data参数的来源。我假设您在构建窗口小部件的函数中连接信号并将它们打包到主窗口中。 (如果你不是,你应该是。)在该函数中,你将有指向按钮和可用组合框的指针。像这样连接你的信号......

g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), combo_box);

...将combo_box作为user_data参数传递给g_signal_connect()。然后指向组合框的指针将被传递给on_button_clicked()回调,伪装成user_data参数。然后,您可以像这样访问它:

void on_button_clicked(GtkButton *button, gpointer user_data)
{
    GtkComboBox *combo_box = GTK_COMBO_BOX(user_data);
    gint item = gtk_combo_box_get_active(combo_box);
    etc.

或者,由于调用堆栈在C中的工作方式,即使通过这样声明你的回调:

void on_button_clicked(GtkButton *button, GtkComboBox *combo_box)

...虽然你失去了GTK_COMBO_BOX()给你的类型检查演员。

答案 1 :(得分:2)

如果返回在C中声明堆栈变量的函数,则该变量不再存在。如果你需要GtkComboBox(或其他对象)来保持,你有几个选择:

  • 使用malloc为其分配空间并传递指针(当您不再需要它时必须释放它)。
  • 使用全局变量
  • 不要使用回调并在外部函数中声明它并传递它。

我可能会使用malloc /传递指针方法,但如果不了解您的情况就无法确定。

答案 2 :(得分:0)

我不确定我是否明白你想要实现的目标。但是,在不使用全局变量的情况下创建持久变量的一种方法是使用静态变量。例如,基于我可能误解你想要的东西你可以做到以下几点:

GtkComboBox *getComboBox()
{
  static GtkComboBox gcb = NULL;

  if (NULL != gcb)
    return gcb;

  // Initialise gcb
  return gcb;
}