Инициализация таблицы 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);
Однако это может быть довольно уродливо, поэтому вы можете просто инициализировать его снаружи.