PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : for(i) g_signal_connect( ..., &i)



dml
14-10-2013, 09:07
Hi,

ich habe einmal wieder ein kleineres Problem bei Gtk. Und zwar benötige ich in der G_Callback Funktion die Elementnummer eines malloc Array`s. Mein Problem ist der gpointer von g_signal_connect. Bei dem Gui-Aufruf wurde die Schleife schon komplett durchlaufen und somit wird bei jedem Knopfdruck die letzte Zahl der Schleife also i=4 übertragen und ein Speicherleck verursacht.

Version 1:


void c_clicked(GtkButton *button, gpointer user_data){
int *i = user_data;
printf(*i=%i\n",*i);
...
extern int *Ary;
printf(Ary[*i]=%i\n",Ary[*i]);
}

int main(){
...
GtkWidget c_button[4];

for(int i=0,i<4, i++){
c_button[i] = gtk_button_new_with_label ("text");
g_signal_connect (c_button[i], "clicked", G_CALLBACK (b_clicked), &i);
}

return 0;
}


Version 2:


typedef struct{
int id;
int *Ary; // ->malloc
} Data;


void c_clicked(GtkButton *button, gpointer user_data){
Data *data = user_data;
printf(%i\n",data->Ary[data->id]);
}

void my_func( int anz, int *array){
...
Data data[anz];

GtkWidget c_button[anz];

for(int i=0,i<=anz, i++){
data[i].id= i;
data[i].Ary = array;

c_button[i] = gtk_button_new_with_label ("text");
g_signal_connect (c_button[i], "clicked", G_CALLBACK (b_clicked), &data[i]);
}

return 0;
}



Habe es jetzt direkt mit der Addresse des Arrayementes versucht also:


g_signal_connect (c_button[i], "clicked", G_CALLBACK (b_clicked), &array[i]);

und funktioniert, doch bringt Problem der konstanten Adresse mit sich.

Vielen Dank für Eure Unterstützung!
dml

locus vivendi
14-10-2013, 14:47
GtkWidget c_button[4];

for(int i=0,i<=4, i++){
c_button[i] = gtk_button_new_with_label ("text");


Mit Gtk kenne ich mich nicht aus. Aber so wie du die Schleife durchläufst wirst du c_button mit 4 indizieren. Das ist verboten - die gültigen Indices sind 0, 1, 2, 3.

Die kanonische Form für Zählschleifen ist

for(count i = 0; i != limit; ++i) count/limit sind natürlich nur Stellvertreter.

Wenn du C++ in der 2011er Version zur Verfügung hast gerne auch wie in

for(widget w : array) { mach_was_mit(w); }

dml
14-10-2013, 18:54
Ups, ausversehen übersehen, ich habe es geändert. Mein Problem ist, das ich nur als Parameter eine Adresse übergeben kann &i und keine Werte i aufgrund des gpointers. Aber danke das Du Dir die Mühe gemacht hast und mir helfen wolltest und ich so unsauberen Quelltext gepostet habe.

sommerfee
14-10-2013, 20:03
Mein Problem ist, das ich nur als Parameter eine Adresse übergeben kann &i und keine Werte i aufgrund des gpointers.
Übergebe GINT_TO_POINTER(i) stattdessen. In dem Signal-Handler kannst du dann den Pointer mittels
int i = GPOINTER_TO_INT(user_data);wieder in einen Integerwert zurückwandeln.

Siehe auch: https://developer.gnome.org/glib/stable/glib-Type-Conversion-Macros.html

dml
15-10-2013, 19:34
Muss mich vielmals bei Dir Bedankem sommerfee! Dein Tip hat mir sehr geholfen. Kann jetzt mit extern int *Ary; weiterarbeiten, was zwar ein ungeliebter Gast in Gui Entwicklungen ist, wegen der Hauptschleife (gtk_main()), doch kann ich mir jetzt erst einmal sicher sein.

Vielen Dank für Deine Bemühung mir zu Helfen.

dml
20-10-2013, 09:42
Habe jetzt das gute Alte:

gtk_widget_set_object_name();
gefunden.



void c_clicked(GtkButton *button, gpointer user_data){
Int* array = user_data;
int value = array[atoi(gtk_widget_get_object_name(button))];
printf(%i\n", value);
}

void my_func( int anz, int *array){
...
char[2] buffer;

GtkWidget c_button[anz];

for(int i=0,i<=anz, i++){
sprintf(buffer,"%i",i);
c_button[i] = gtk_button_new_with_label ("textt);
gtk_widget_set_object_name(buffer);
g_signal_connect (c_button[i], "clicked", G_CALLBACK (b_clicked), array);
}

return 0;
}


Und kann auf extern verzichten.

sommerfee
20-10-2013, 12:44
Warum übergibst du nicht einfach array+i statt array?



void c_clicked(GtkButton *button, gpointer user_data){
Int* array_i = user_data;
int value = *array_i;
printf(%i\n", value);
}

void my_func( int anz, int *array){
...
GtkWidget c_button[anz];

for(int i=0,i<=anz, i++){
c_button[i] = gtk_button_new_with_label ("text");
g_signal_connect (c_button[i], "clicked", G_CALLBACK (b_clicked), array + i);
}

return 0;
}

dml
20-10-2013, 14:24
Coole Idee, kannte ich noch nicht, vor allem da set_object_name eigentlich nicht zur Wertübergabe gedacht ist. Ich werde es morgen gleich ausprobieren, vor allem, ob es auch mit struct's funktioniert.Danke.

sommerfee
20-10-2013, 16:19
BTW:
for(int i=0,i<=anz, i++){ ist (immer noch) falsch, es muß
for(int i=0,i<anz, i++){ heißen. (Siehe auch http://www.mrunix.de/forums/showpost.php?p=355698&postcount=2 )

dml
30-10-2013, 11:18
Na an dem Quellcode war so einiges falsch. Ich wollte nicht den gesamten ursprünglichen verwenden. Hätten diesen aber vorher testen müssen.