如何设置指向结构的 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_parametersreturns之后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;
}

我认错了。我一直很傻。我的棕色包已经穿上了,我邀请所有来者因为我的愚蠢而将我投票给一个冒烟的洞。反正我是不会看的

非常抱歉浪费了您的时间。