如何设置指向结构的 Gtk gpointer?
How do I set up a Gtk gpointer to a struct?
我正在尝试通过编写一些函数来帮助我使用 Gtk 来让自己的生活更轻松(而且我很害怕做一顿饭)。感觉离我很近了,就是没有雪茄。
我已经定义了几个结构:
typedef struct action_param {
void (*action_ptr)();
gpointer parameter;
} action_param_type;
typedef struct document {
GtkWindow *parent_window;
void (*save_action_ptr)();
void (*open_action_ptr)();
gchar* filename;
void* filedata;
} document_type;
我有设置它们的函数:
document_type build_document_with_characteristics(GtkWindow *parent_window,
void (*save_action_ptr),
void (*open_action_ptr),
gpointer filename,
gpointer filedata) {
struct document doc;
doc.parent_window = parent_window;
doc.save_action_ptr = save_action_ptr;
doc.open_action_ptr = open_action_ptr;
doc.filename = filename;
doc.filedata = filedata;
return doc;
}
action_param_type set_action_with_parameter(void (*action_ptr), gpointer action_parameter) {
action_param_type action;
action.action_ptr = action_ptr;
/*** these two lines for testing */
struct document *mydata = action_parameter;
// g_print("%s",mydata->filename);
action.parameter = action_parameter;
return action;
}
GtkWidget* create_menuitem_with_parameters(void* parent_menu, char* label, struct action_param menuaction) {
GtkWidget *menuitem = gtk_menu_item_new_with_label(label);
gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), menuitem);
if (menuaction.action_ptr != NULL) {
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menuaction.action_ptr), &menuaction.parameter);
}
return menuitem;
}
调用如下:
struct document this_document = build_document_with_characteristics(GTK_WINDOW(window),&handle_save,&handle_open,"Test Title","Test Document");
create_menuitem_with_parameters(fileMenu, "Save", set_action_with_parameter(&show_save_dialogue,&this_document));
我现在的问题(我相信我会发现更多问题)是,如果我取消注释 g_print 行(这是为了查看我是否正确填充了所有内容), 我得到:
Segmentation fault: 11
我想知道问题是否出在这一行:
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menuaction.action_ptr), &menuaction.parameter);
我觉得我错过了一些明显的东西 - 那是什么?
您正在向回调传递一个临时指针。
GtkWidget* create_menuitem_with_parameters(void* parent_menu, char* label, struct action_param menuaction)
将 menuaction 定义为通过副本传递。意思是在create_menuitem_with_parameters
returns之后g_signal_connect
传入的指针已经不存在了。您需要将 menuaction
对象存储在某处并确保它在回调的 运行 时刻有效。
好的。棕色纸袋时间。我发现了问题(对于在这里发布问题的任何人,提醒您不要过度编辑问题)。事实是我在早期的函数中调用 set_action_with_parameter 并将 action_parameter 设置为 NULL。只要我不尝试使用它,这就不是问题。不过,一旦我 g_print 出现段错误。
@pan-mroku 就他们而言是正确的——但这也符合我的过度编辑。
解决方案很简单 - 只需在使用前检查它是否为 NULL:
action_param set_action_with_parameter(void (*action_ptr), gpointer action_parameter) {
action_param action;
action.action_ptr = action_ptr;
if (action_parameter != NULL) {
action.parameter = &action_parameter;
struct document *mydata = action_parameter;
g_print("%s",mydata->filename);
}
return action;
}
我认错了。我一直很傻。我的棕色包已经穿上了,我邀请所有来者因为我的愚蠢而将我投票给一个冒烟的洞。反正我是不会看的
非常抱歉浪费了您的时间。
我正在尝试通过编写一些函数来帮助我使用 Gtk 来让自己的生活更轻松(而且我很害怕做一顿饭)。感觉离我很近了,就是没有雪茄。
我已经定义了几个结构:
typedef struct action_param {
void (*action_ptr)();
gpointer parameter;
} action_param_type;
typedef struct document {
GtkWindow *parent_window;
void (*save_action_ptr)();
void (*open_action_ptr)();
gchar* filename;
void* filedata;
} document_type;
我有设置它们的函数:
document_type build_document_with_characteristics(GtkWindow *parent_window,
void (*save_action_ptr),
void (*open_action_ptr),
gpointer filename,
gpointer filedata) {
struct document doc;
doc.parent_window = parent_window;
doc.save_action_ptr = save_action_ptr;
doc.open_action_ptr = open_action_ptr;
doc.filename = filename;
doc.filedata = filedata;
return doc;
}
action_param_type set_action_with_parameter(void (*action_ptr), gpointer action_parameter) {
action_param_type action;
action.action_ptr = action_ptr;
/*** these two lines for testing */
struct document *mydata = action_parameter;
// g_print("%s",mydata->filename);
action.parameter = action_parameter;
return action;
}
GtkWidget* create_menuitem_with_parameters(void* parent_menu, char* label, struct action_param menuaction) {
GtkWidget *menuitem = gtk_menu_item_new_with_label(label);
gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), menuitem);
if (menuaction.action_ptr != NULL) {
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menuaction.action_ptr), &menuaction.parameter);
}
return menuitem;
}
调用如下:
struct document this_document = build_document_with_characteristics(GTK_WINDOW(window),&handle_save,&handle_open,"Test Title","Test Document");
create_menuitem_with_parameters(fileMenu, "Save", set_action_with_parameter(&show_save_dialogue,&this_document));
我现在的问题(我相信我会发现更多问题)是,如果我取消注释 g_print 行(这是为了查看我是否正确填充了所有内容), 我得到:
Segmentation fault: 11
我想知道问题是否出在这一行:
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menuaction.action_ptr), &menuaction.parameter);
我觉得我错过了一些明显的东西 - 那是什么?
您正在向回调传递一个临时指针。
GtkWidget* create_menuitem_with_parameters(void* parent_menu, char* label, struct action_param menuaction)
将 menuaction 定义为通过副本传递。意思是在create_menuitem_with_parameters
returns之后g_signal_connect
传入的指针已经不存在了。您需要将 menuaction
对象存储在某处并确保它在回调的 运行 时刻有效。
好的。棕色纸袋时间。我发现了问题(对于在这里发布问题的任何人,提醒您不要过度编辑问题)。事实是我在早期的函数中调用 set_action_with_parameter 并将 action_parameter 设置为 NULL。只要我不尝试使用它,这就不是问题。不过,一旦我 g_print 出现段错误。
@pan-mroku 就他们而言是正确的——但这也符合我的过度编辑。
解决方案很简单 - 只需在使用前检查它是否为 NULL:
action_param set_action_with_parameter(void (*action_ptr), gpointer action_parameter) {
action_param action;
action.action_ptr = action_ptr;
if (action_parameter != NULL) {
action.parameter = &action_parameter;
struct document *mydata = action_parameter;
g_print("%s",mydata->filename);
}
return action;
}
我认错了。我一直很傻。我的棕色包已经穿上了,我邀请所有来者因为我的愚蠢而将我投票给一个冒烟的洞。反正我是不会看的
非常抱歉浪费了您的时间。