Как мне настроить Gtk Gpointer для структуры? - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь облегчить себе жизнь (и, боюсь, готовлю еду), написав некоторые функции, которые помогут мне с 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);

Я чувствую, чтоЯ только что пропустил что-то очевидное - но что это?

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Хорошо. Коричневый бумажный пакет времени. Я обнаружил проблему (и для любого, кто публикует здесь вопрос, пусть это будет напоминанием о том, чтобы вы не перередактировали проблему). Правда в том, что я вызывал set_action_with_parameter в более ранней функции с параметром action_parameter, установленным в NULL. Что не было проблемой, пока я не пытался им пользоваться. Как только я g_print'd, Seg Fault.

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

Mea culpa. Я был очень глупым. Моя коричневая сумка надета, и я приглашаю всех желающих проголосовать за меня в курительной яме за мою глупость. Я все равно этого не увижу.

Мне очень жаль, что я потратил ваше время.

1 голос
/ 28 октября 2019

Вы передаете временный указатель на обратный вызов.

GtkWidget* create_menuitem_with_parameters(void* parent_menu, char* label, struct action_param menuaction) определяет действие меню как переданное копией. Это означает, что после возврата create_menuitem_with_parameters указатель, переданный в g_signal_connect, больше не существует. Вам нужно где-то хранить объект menuaction и убедиться, что он действителен в момент выполнения обратного вызова.

...