Инициализация таблицы GtkWidget* в C

Я пишу простое приложение на C с GTK2.

У меня есть небольшая проблема - я должен создать 9x9 таблица входных виджетов, так что я думаю, что это хорошая идея - создать массив GtkWidgetи использовать его в петлях и т. д.

Но... моя программа падает, когда я передаю элемент этого массива в функцию GTK.

Я объявляю массив следующим образом:

GtkWidget* entries[9][9];

позже у меня есть функция:

void drawBoard(GtkWidget* table, GtkWidget* entries[][9])
{
    for(last_i=1; last_i<10; last_i++)
    {
        for(last_j=1; last_j<10; last_j++)
        {
            addField(entries[last_i-1][last_j-1],table);
        }
    }
}

И, наконец, в addField Я использую запись как это:

void addField(GtkWidget* field, GtkWidget *table)
{
    field = gtk_entry_new_with_max_length(1);
    //rest of code
}

После этого, когда я пытаюсь получить доступ к элементам, которые я инициализировал в приведенном выше коде, происходит сбой программы, например:

void function(GtkWidget *entries[][9])
{
    int i,j=0;
    for(i=0; i<9; i++)
    {
        for(j=0; j<9; j++)
        {
            gtk_entry_set_width_chars(entries[i][j], 2);//<-- here app crashes
        }
    }
}

1 ответ

Решение

Если я не ошибаюсь, вы, кажется, не инициализируете entires в любом месте. В результате в

addField(entries[i][j],table,i,j);

Я думаю, что вы передаете кучу совершенно случайных указателей, которые приводят к segfaulting.

Попробуйте инициализировать entries во-первых, например:

for(i=0; i<9; i++)
{
    for(j=0; j<9; j++)
    {
        entries[i][j] = gtk_label_new ("button");
        addField(entries[i][j],table,i,j);
        fprintf(stderr,"%d %d",i,j);
    }
}

РЕДАКТИРОВАТЬ: Вы упоминаете в своем комментарии, что вы инициализируете его в addField,

Я не заметил этого, на самом деле я не удосужился искать инициализацию внутри addField (по причинам, которые скоро станут очевидными).

Виноват.

Посмотрим, что происходит.

Вы создаете свой объект в рамках addField и назначив его указателю GtkWidget* field,

Хорошо, но это указатель GtkWidget* field передается по значению или по ссылке?

По значению, так что вы делаете внутри void addField не влияет на стоимость entries[i][j],

Если вы выполняли операции над (ранее существовавшим) объектом, не изменяя значение указателя, да - это в значительной степени то, для чего хороши указатели - но если вы изменяете значение самого указателя, нет.

Так что вам нужно передать указатель на указатель, что-то с эффектом

void addField(GtkWidget** field, GtkWidget *table, int i, int j)
{
    *field = gtk_entry_new_with_max_length(1);
    gtk_table_attach_defaults (GTK_TABLE (table), *field, j, j+1, i, i+1);
    gtk_widget_show (*field);
    gtk_entry_set_width_chars((GtkEntry*)*field, 2);
    gtk_widget_modify_font(*field, pango_font_description_from_string("Tahoma 25.4"));
    g_object_set_data(G_OBJECT(*field), "i", last_i);
    g_object_set_data(G_OBJECT(*field), "j", last_j);
    g_signal_connect (*field, "insert-text",
                      G_CALLBACK (edited_callback),
                      *field
                     );

}

и конечно

        addField(&entries[i][j],table,i,j);

Однако это может быть довольно уродливо, поэтому вы можете просто инициализировать его снаружи.

Другие вопросы по тегам