通过GTK的g_signal_connect()传递回调参数会导致C中出现意外值

mspsb9vt  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(117)

我正在使用GTK 4和Miniaudio进行一个小项目。我需要通过g_signal_connect()向几个小部件传递一些参数。由于我是GTK新手,所以我尝试在GTK's Getting started上使用一个基本的GTK示例(hello-world-gtk示例)进行实验。但是,当我通过g_signal_connect()传递任何回调参数时,我得到了意外的值。
下面是修改后的hello-world-gtk代码示例:

#include <stdio.h>
#include <gtk/gtk.h>

void hello(GtkWidget *widget, void *data) {
  printf("pointer in hello(): %p\n", data);
  printf("data value: %d\n", *(int*)data);
}

void activate(GtkApplication *app, gpointer user_data) {
  GtkWidget *window;
  GtkWidget *button;

  int abc = 5;
  void *ptr = &abc;

  window = gtk_application_window_new(app);
  gtk_window_set_title(GTK_WINDOW(window), "Window");
  gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);

  button = gtk_button_new_with_label("Hello World");

  printf("pointer in activate(): %p\n", ptr);
  printf("abc value: %d\n", *(int*)ptr);
  // Problem occurs here.
  g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(hello), ptr);
  gtk_window_set_child(GTK_WINDOW(window), button);

  gtk_window_present(GTK_WINDOW(window));
}

int main(int argc, char **argv) {
  GtkApplication *app;
  int status;

  app = gtk_application_new("org.gtk.example", G_APPLICATION_REPLACE);
  g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
  status = g_application_run(G_APPLICATION(app), argc, argv);
  g_object_unref(app);

  return status;
}

使用gcc $(pkg-config --cflags gtk4) -o hello-world-gtk hello-world-gtk.c $(pkg-config --libs gtk4)命令编译。
终端输出为:

pointer in activate(): 0x7fff5f4c8124
abc value: 5
pointer in hello(): 0x7fff5f4c8124
data value: 0
pointer in hello(): 0x7fff5f4c8124
data value: 0

在初始化时,终端中的前两行被打印出来,并且在每次单击按钮时,新的两行被打印出来(“hello()中的指针:...”和“数据值:...”)。
我希望,正如我可能猜到的那样,传递指针的值被打印出来,而不是每次都是0,或者:

pointer in activate(): 0x7fff5f4c8124
abc value: 5
pointer in hello(): 0x7fff5f4c8124
data value: 5
pointer in hello(): 0x7fff5f4c8124
data value: 5

我试着在谷歌上搜索其他人如何使用函数g_signal_connect(),语法非常相似,但他们得到了预期的值(就像here,创建了我的小代码演示,看看我是否理解C中的void* 和回调函数,但我在那个演示中得到了预期的值。
Demo:

#include <stdio.h>

void doing_things(int (*fx)(int), void *param) {
  int x = *(int*)param;
  printf("Applied function: %d\n", fx(x));
}

int square(int value) {
  return value * value;
}

int main() {
  int my_val = 5;
  int (*my_square)(int) = square;
  void *my_pointer = &my_val;
  doing_things(my_square, my_pointer);
  return 0;
}

Demo的输出:

Applied function: 25

我试过改变data的类型,并将其类型转换为不同的类型(gpointer基本上是void*),但没有成功。
我有一个想法,使回调参数extern,但它被认为是一个回实践我知道多少。
如果你知道如何解决这个问题,我会非常感激!
先谢了。

dzhpxtsq

dzhpxtsq1#

int abc = 5;

这个变量是activate()函数的局部变量,你提供给g_signal_connect的指针.

g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(hello), ptr);

......将在activate()返回后立即挂起。因此,在hello()中解引用指针具有 *undefined行为 *。
一个简单的修复方法是将其设置为static,以使变量在程序执行结束前一直存在:

static int abc = 5;

相关问题