我正在用C语言做一个使用GTK4和迷你音频的小项目.我需要通过g_Signal_Connect()将一些参数传递给几个小部件.因为我是GTK的新手,所以我try 在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

在初始化时,打印终端中的前两行,并在每次单击按钮时打印出新的两行("POINTER in 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,创建了我的小代码演示来查看我是否理解了VALID*和C回调,但我在该演示中得到了期望值.

演示:

#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;
}

演示的输出:

Applied function: 25

我try 过更改data的类型并将其转换为不同的类型(gpointer基本上是void*),但没有成功.

我有一个 idea ,将回调参数设置为extern,但这被认为是我所知道的回调练习.

如果你知道如何解决这个问题,我将不胜感激!

先谢谢你.

推荐答案

int abc = 5;

此变量是activate()函数的本地变量,您提供的指向g_signal_connect的指针...

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

...会在activate()次返回时就开始摇摆.因此,取消引用hello()内的指针的值为undefined behavior.

一种简单的解决方法是将其设置为static,以使变量一直存在到程序执行结束:

static int abc = 5;

C++相关问答推荐

ARM上的Modulo Sim Aarch 64(NEON)

C中的ATONE会扰乱SEN/CLUTE GMS应用程序中的其他字符串

错误:在.h程序中重新定义 struct

C如何显示字符串数组中的第一个字母

MISRA C:2012 11.3违规强制转换(FLOAT*)到(uint32_t*)

如何知道我是否从非阻塞套接字读取所有内容

为什么即使在强制转换时,此代码也会溢出?

文件权限为0666,但即使以超级用户身份也无法打开

如何使用[BTStack]BLE发送大型(>;2kb)信息包

理解C版宏(看起来像未声明的变量?)

什么是.c.h文件?

在另一个函数中使用realloc和指针指向指针

如何在MSVC中使用intSafe.h函数?

将size_t分配给off_t会产生符号转换错误

x86-64平台上的int_fast8_t大小与int_fast16_t大小

在分配内存后使用指针是未定义的行为吗?

我的代码可以与一个编译器一起使用,但不能与其他编译器一起使用

在C中交换字符串和数组的通用交换函数

为什么使用 C 引用这个 char 数组会导致 Stack smasing?

将帧从相机 (/dev/video0) 复制到帧缓冲区 (/dev/fb0) 会产生意外结果