Search code examples
cgtkgtk3

How do I set up a Gtk gpointer to a struct?


I'm trying to make life easier for myself (and making a meal of it, I'm afraid) by writing some functions to help me with Gtk. It feels like I'm close, but no cigar.

I've defined a couple of structures:

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;

And I've got functions which sets them up:

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

Which is called as follows:

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));

My problem at the moment (and I'm sure that I'll find some more problems) is that if I uncomment the g_print line (which is there to see if I've populated everything correctly), I get:

Segmentation fault: 11

I was wondering if the problem might be with this line:

g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menuaction.action_ptr), &menuaction.parameter);

I feel like I've just missed something obvious - but what is it?


Solution

  • I was calling set_action_with_parameter in an earlier function with action_parameter set to NULL. Which wasn't a problem as long as I didn't try to use it. As soon as I g_print'd though, Seg Fault.

    @pan-mroku is right as far as they go - but this fits into my over-editing too.

    The solution was simple - just check if it's NULL before using it:

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