Messieurs dames, bien le bonsoir ^^
J'ai repris mes études depuis septembre dernier et pour ne pas que je m'ennui cette été on m'a confié la tache de faire un chat en C, avec GTK+ et glade 2.
Je me suis bien familiarisé avec GTK+ et depuis quelques jours (semaines) je cherche à y intégrer des threads mais je bloque...
voici mon problème, je souhaiterais créé un thread via un callback (clique bouton), et en même temps passer des arguments à la fonction appelée.
Le thread se crée bien sauf que les paramètres n'arrivent pas à la fonction... et je n'arrive pas à trouver pourquoi...
voici mes fichiers de code : (ils sont aussi dans le tar.gz joint)
main.c
interface.c :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <gtk/gtk.h> #include <pthread.h> #include "interface.h" #include "support.h" #include "MesFonctions.h" int main (int argc, char *argv[]) { GtkWidget *chat_window; #ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif /* init threads */ g_thread_init (NULL); gdk_threads_init (); gdk_threads_enter (); gtk_init (&argc, &argv); chat_window = create_chat_window (); gtk_widget_show (chat_window); gtk_main (); gdk_threads_leave (); return 0; }
interface.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> #include "callbacks.h" #include "interface.h" #include "support.h" #define GLADE_HOOKUP_OBJECT(component,widget,name) \ g_object_set_data_full (G_OBJECT (component), name, \ gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) #define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ g_object_set_data (G_OBJECT (component), name, widget) GtkWidget* create_chat_window (void) { GtkWidget *chat_window; GtkWidget *vbox1; GtkWidget *vbox2; GtkWidget *pseudo_entry; GtkWidget *IP_entry; GtkWidget *connexion_bouton; GtkWidget *chat_view_scroll; GtkWidget *chat_view; GtkWidget *chat_entry_scroll; GtkWidget *chat_entry; GtkWidget *send_bouton; chat_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_size_request (chat_window, 350, 600); gtk_container_set_border_width (GTK_CONTAINER (chat_window), 5); gtk_window_set_title (GTK_WINDOW (chat_window), _("Chat windows")); gtk_window_set_resizable (GTK_WINDOW (chat_window), FALSE); gtk_window_set_position(GTK_WINDOW(chat_window),GTK_WIN_POS_CENTER); vbox1 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (chat_window), vbox1); vbox2 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0); pseudo_entry = gtk_entry_new (); gtk_widget_show (pseudo_entry); gtk_box_pack_start (GTK_BOX (vbox2), pseudo_entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (pseudo_entry), _("Pseudo")); gtk_entry_set_invisible_char (GTK_ENTRY (pseudo_entry), 8226); IP_entry = gtk_entry_new (); gtk_widget_show (IP_entry); gtk_box_pack_start (GTK_BOX (vbox2), IP_entry, FALSE, FALSE, 0); gtk_entry_set_text (GTK_ENTRY (IP_entry), _("IP du server")); gtk_entry_set_invisible_char (GTK_ENTRY (IP_entry), 8226); connexion_bouton = gtk_button_new_with_mnemonic (_("Connexion au server")); gtk_widget_show (connexion_bouton); gtk_box_pack_start (GTK_BOX (vbox2), connexion_bouton, FALSE, FALSE, 0); chat_view_scroll = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (chat_view_scroll); gtk_box_pack_start (GTK_BOX (vbox1), chat_view_scroll, TRUE, TRUE, 0); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (chat_view_scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (chat_view_scroll), GTK_SHADOW_IN); chat_view = gtk_text_view_new (); gtk_widget_show (chat_view); gtk_container_add (GTK_CONTAINER (chat_view_scroll), chat_view); gtk_widget_set_size_request (chat_view, -1, 503); gtk_container_set_border_width (GTK_CONTAINER (chat_view), 4); gtk_widget_set_sensitive (chat_view, FALSE); GTK_WIDGET_UNSET_FLAGS (chat_view, GTK_CAN_FOCUS); gtk_text_view_set_editable (GTK_TEXT_VIEW (chat_view), FALSE); gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW (chat_view), FALSE); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (chat_view), GTK_WRAP_WORD); gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (chat_view), FALSE); chat_entry_scroll = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (chat_entry_scroll); gtk_box_pack_start (GTK_BOX (vbox1), chat_entry_scroll, FALSE, TRUE, 0); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (chat_entry_scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (chat_entry_scroll), GTK_SHADOW_IN); chat_entry = gtk_text_view_new (); gtk_widget_show (chat_entry); gtk_container_add (GTK_CONTAINER (chat_entry_scroll), chat_entry); gtk_widget_set_size_request (chat_entry, -1, 95); gtk_container_set_border_width (GTK_CONTAINER (chat_entry), 4); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (chat_entry), GTK_WRAP_WORD); gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat_entry)), _("Zone de saisie"), -1); send_bouton = gtk_button_new_with_mnemonic (_("Envoyer")); gtk_widget_show (send_bouton); gtk_box_pack_start (GTK_BOX (vbox1), send_bouton, FALSE, FALSE, 0); gtk_widget_show_all(chat_window); g_signal_connect ((gpointer) pseudo_entry, "insert_text", G_CALLBACK (on_pseudo_entry_insert_text), NULL); g_signal_connect ((gpointer) IP_entry, "insert_text", G_CALLBACK (on_IP_entry_insert_text), NULL); g_signal_connect ((gpointer) connexion_bouton, "clicked", G_CALLBACK (on_connexion_bouton_clicked), NULL); g_signal_connect ((gpointer) send_bouton, "clicked", G_CALLBACK (on_send_bouton_clicked), NULL); g_signal_connect(chat_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* Store pointers to all widgets, for use by lookup_widget(). */ GLADE_HOOKUP_OBJECT_NO_REF (chat_window, chat_window, "chat_window"); GLADE_HOOKUP_OBJECT (chat_window, vbox1, "vbox1"); GLADE_HOOKUP_OBJECT (chat_window, vbox2, "vbox2"); GLADE_HOOKUP_OBJECT (chat_window, pseudo_entry, "pseudo_entry"); GLADE_HOOKUP_OBJECT (chat_window, IP_entry, "IP_entry"); GLADE_HOOKUP_OBJECT (chat_window, connexion_bouton, "connexion_bouton"); GLADE_HOOKUP_OBJECT (chat_window, chat_view_scroll, "chat_view_scroll"); GLADE_HOOKUP_OBJECT (chat_window, chat_view, "chat_view"); GLADE_HOOKUP_OBJECT (chat_window, chat_entry_scroll, "chat_entry_scroll"); GLADE_HOOKUP_OBJECT (chat_window, chat_entry, "chat_entry"); GLADE_HOOKUP_OBJECT (chat_window, send_bouton, "send_bouton"); return chat_window; }
callback.c :Code:GtkWidget* create_chat_window (void);
callback.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <gtk/gtk.h> #include <string.h> #include <unistd.h> //#include "callbacks.h" #include "interface.h" #include "support.h" #include "MesFonctions.h" void on_pseudo_entry_insert_text (GtkEditable *editable, gchar *new_text, gint new_text_length, gpointer position, gpointer user_data) { } void on_IP_entry_insert_text (GtkEditable *editable, gchar *new_text, gint new_text_length, gpointer position, gpointer user_data) { } void on_connexion_bouton_clicked (GtkButton *button, gpointer user_data) { ID_player info_player; GError *error = NULL; GtkWidget * ID_pseudo_entry = lookup_widget(GTK_WIDGET(button),"pseudo_entry"); GtkWidget * ID_IP_entry = lookup_widget(GTK_WIDGET(button),"IP_entry"); // info_player.Pseudo = gtk_entry_get_text(GTK_ENTRY(ID_pseudo_entry)); // info_player.pIP = gtk_entry_get_text(GTK_ENTRY(ID_IP_entry)); info_player.Pseudo = "ludo"; info_player.pIP = "192.168.36.100"; g_print("Pseudo = %s\tIP = %s\n",info_player.Pseudo, info_player.pIP); if(!g_thread_create(monthread, &info_player, TRUE, &error)) { g_printerr ("Failed to create YES thread: %s\n", error->message); } gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); // pour rendre inactif le bouton (grisé) } void on_send_bouton_clicked (GtkButton *button, gpointer user_data) { GtkWidget * pchat_entry = lookup_widget(GTK_WIDGET(button),"chat_entry"); GtkWidget * pchat_view = lookup_widget(GTK_WIDGET(button),"chat_view"); GtkTextBuffer * pTextBuffer; GtkTextBuffer * pTextBufferView; GtkTextIter iStart; GtkTextIter iEnd; gchar * sBuffer; gchar * PlayerName = "ludo a dit : " ; GtkTextIter StartLine; pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pchat_entry)); pTextBufferView = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pchat_view)); gtk_text_buffer_get_start_iter(pTextBuffer, &iStart); // on récupère l'origine du buffer gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd); // on récupère la fin du buffer sBuffer = gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE); gtk_text_buffer_get_end_iter(pTextBufferView, &StartLine); gtk_text_buffer_insert (pTextBufferView, &StartLine, g_strconcat(PlayerName,sBuffer, "\n",NULL), -1); // pour vider le buffer de saisie gtk_text_buffer_get_bounds (pTextBuffer, &iStart, &iEnd); gtk_text_buffer_delete (pTextBuffer, &iStart, &iEnd); gtk_text_view_set_buffer(GTK_TEXT_VIEW(pchat_entry),pTextBuffer); g_free(sBuffer); }
support.c :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <gtk/gtk.h> void on_pseudo_entry_insert_text (GtkEditable *editable, gchar *new_text, gint new_text_length, gpointer position, gpointer user_data); void on_IP_entry_insert_text (GtkEditable *editable, gchar *new_text, gint new_text_length, gpointer position, gpointer user_data); void on_send_bouton_clicked (GtkButton *button, gpointer user_data); void on_connexion_bouton_clicked (GtkButton *button, gpointer user_data);
support.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <gtk/gtk.h> #include "support.h" GtkWidget* lookup_widget (GtkWidget *widget, const gchar *widget_name) { GtkWidget *parent, *found_widget; for (;;) { if (GTK_IS_MENU (widget)) parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); else parent = widget->parent; if (!parent) parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); if (parent == NULL) break; widget = parent; } found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), widget_name); if (!found_widget) g_warning ("Widget not found: %s", widget_name); return found_widget; } static GList *pixmaps_directories = NULL; /* Use this function to set the directory containing installed pixmaps. */ void add_pixmap_directory (const gchar *directory) { pixmaps_directories = g_list_prepend (pixmaps_directories, g_strdup (directory)); } /* This is an internally used function to find pixmap files. */ static gchar* find_pixmap_file (const gchar *filename) { GList *elem; /* We step through each of the pixmaps directory to find it. */ elem = pixmaps_directories; while (elem) { gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, G_DIR_SEPARATOR_S, filename); if (g_file_test (pathname, G_FILE_TEST_EXISTS)) return pathname; g_free (pathname); elem = elem->next; } return NULL; } /* This is an internally used function to create pixmaps. */ GtkWidget* create_pixmap (GtkWidget *widget, const gchar *filename) { gchar *pathname = NULL; GtkWidget *pixmap; if (!filename || !filename[0]) return gtk_image_new (); pathname = find_pixmap_file (filename); if (!pathname) { g_warning (_("Couldn't find pixmap file: %s"), filename); return gtk_image_new (); } pixmap = gtk_image_new_from_file (pathname); g_free (pathname); return pixmap; } /* This is an internally used function to create pixmaps. */ GdkPixbuf* create_pixbuf (const gchar *filename) { gchar *pathname = NULL; GdkPixbuf *pixbuf; GError *error = NULL; if (!filename || !filename[0]) return NULL; pathname = find_pixmap_file (filename); if (!pathname) { g_warning (_("Couldn't find pixmap file: %s"), filename); return NULL; } pixbuf = gdk_pixbuf_new_from_file (pathname, &error); if (!pixbuf) { fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", pathname, error->message); g_error_free (error); } g_free (pathname); return pixbuf; } /* This is used to set ATK action descriptions. */ void glade_set_atk_action_description (AtkAction *action, const gchar *action_name, const gchar *description) { gint n_actions, i; n_actions = atk_action_get_n_actions (action); for (i = 0; i < n_actions; i++) { if (!strcmp (atk_action_get_name (action, i), action_name)) atk_action_set_description (action, i, description); } }
MesFonctions.c :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <gtk/gtk.h> /* * Standard gettext macros. */ #ifdef ENABLE_NLS # include <libintl.h> # undef _ # define _(String) dgettext (PACKAGE, String) # define Q_(String) g_strip_context ((String), gettext (String)) # ifdef gettext_noop # define N_(String) gettext_noop (String) # else # define N_(String) (String) # endif #else # define textdomain(String) (String) # define gettext(String) (String) # define dgettext(Domain,Message) (Message) # define dcgettext(Domain,Message,Type) (Message) # define bindtextdomain(Domain,Directory) (Domain) # define _(String) (String) # define Q_(String) g_strip_context ((String), (String)) # define N_(String) (String) #endif GtkWidget* lookup_widget (GtkWidget *widget, const gchar *widget_name); /* Use this function to set the directory containing installed pixmaps. */ void add_pixmap_directory (const gchar *directory); /* * Private Functions. */ /* This is used to create the pixmaps used in the interface. */ GtkWidget* create_pixmap (GtkWidget *widget, const gchar *filename); /* This is used to create the pixbufs used in the interface. */ GdkPixbuf* create_pixbuf (const gchar *filename); /* This is used to set ATK action descriptions. */ void glade_set_atk_action_description (AtkAction *action, const gchar *action_name, const gchar *description);
MesFonctions.h :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <gtk/gtk.h> #include "MesFonctions.h" //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Fonction de test //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void *monthread (void* args) { ID_player *data = args; while(1) { g_print("data = %s\n",data->Pseudo); sleep(2); } }
Je sens bien qu'il y a un problème avec la mémoire, mais je ne comprend pas pourquoi d'autant que si je déplace la création du thread dans le main ça marche très bien...Code:
1
2
3
4
5
6
7
8
9
10
11 #ifndef MESFONCTIONS #define MESFONCTIONS typedef struct { gchar * Pseudo; gchar * pIP; } ID_player; void *monthread (void* args); #endif
A votre bon coeur messieurs dames :calim2:
Bonne soirée et merci pour ceux qui auront déjà eu le courage d'arriver si bas dans ce post... ;)
++