C 和 GTK 传递参数

C and GTK Passing parameters

以下程序将无法编译。我已将代码缩减为这个简单的程序。我已经发布了编译命令及其输出。

#include <gtk/gtk.h>

void update_label(GtkLabel *glab);

void update_label(GtkLabel *glab)
{
}

int main(int argc, char *argv[])
{
  GtkWidget *lbl;

  gtk_init(&argc, &argv);

  lbl = gtk_label_new("Hi");

  update_label(lbl);

  gtk_main();

  return 0;
}

编译器输出为:

graeme@graeme-HP-xw4300-Workstation ~/c/label $ gcc `pkg-config --cflags gtk+-3.0` my04.c -o my04 `pkg-config --libs gtk+-3.0`
my04.c: In function ‘main’:
my04.c:17:3: warning: passing argument 1 of ‘update_label’ from incompatible pointer type [enabled by default]
   update_label(lbl);
   ^
my04.c:5:6: note: expected ‘struct GtkLabel *’ but argument is of type ‘struct GtkWidget *’
 void update_label(GtkLabel *glab)
      ^

您声明 update_label 接受 GtkLabel* 参数:

void update_label(GtkLabel *glab);

另一方面,您将参数 lbl 传递给它 GtkWidget*:

GtkWidget *lbl;
(...)
update_label(lbl);

这就是编译器引发错误 "passing argument 1 of ‘update_label’ from incompatible pointer type" 的原因,甚至进一步解释:

my04.c:5:6: note: expected ‘struct GtkLabel *’ but argument is of type ‘struct GtkWidget *’
 void update_label(GtkLabel *glab)

要解决这个问题,您必须将 lbl 向上转换为 GtkLabel*,因为该变量指向的对象实际上是 GtkLabel:

update_label(GTK_LABEL(lbl));

https://developer.gnome.org/gobject/stable/gtype-conventions.html

对于 C 中的 GTK,您需要大量的指针转换。 由于某种原因,所有创建者函数 return GtkWidget* 但所有相关的修饰函数都需要适当的指针指向 GtkLabel* 等。

为此,GTK 提供了类型转换宏。

您可以使用GTK_LABEL()宏来转换您的指针。 对于其他类型的小部件,您有 GTK_WINDOWGTK_MENU_ITEM 和更多此类宏。

首先这很烦人。

当涉及来自接口或父对象的函数时 "class"(不是真正的 OO 类),您需要选择正确的类型并进行适当的转换。