IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Passage d'arguments par pointeur sur structure et segfault


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 52
    Par défaut Passage d'arguments par pointeur sur structure et segfault
    Bonjour à tous,

    Je suis en train d'essayer de développer un petit mixer son avec une interface graphique GTK.
    Je crée un second thread grâce à g_idle_add() et comme ma fonction avait besoin de plus d'arguments (g_idle_add est limité à 1 argument), j'ai crée un pointeur sur structure pour passer plusieurs arguments à cette fonction : l'objet slider et le volume.

    Mon soucis se situe au niveau des fonctions GTK comme gtk_range_get_value() et gtk_range_set_value() qui me créent des segmentation fault.

    J'ai beau chercher je n'arrive pas à en trouver la cause ...
    J'ai essayé de revoir mes cours sur les pointeurs mais pas moyen de trouver où est l'erreur.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    #include <gtk/gtk.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <math.h>
    #include <alsa/asoundlib.h>
    #include <alsa/mixer.h>
     
    struct soundth_args {
    	long volume;
    	GtkScale *slider;
    };
     
    int       	sound_thread(gpointer user_data);
    int		get_volume(long *volume);
    //int		write_volume(const char mixer[], gdouble volume);
    static void	quit(GtkWidget *icon, gpointer user_data); 
    static void	show_window(GtkWidget *icon, GtkWidget *win);
    static void	slider_moved(GtkWidget *range, gpointer user_data);
    static void	view_popup_menu(GtkWidget *icon, gpointer user_data);
     
     
    int
    sound_thread(gpointer user_data) {
    	struct soundth_args *args = user_data;
    	if(get_volume(args->volume) != gtk_range_get_value(GTK_RANGE(&(args->slider)))) {
    		get_volume(&(args->volume));
    		g_print("%d\n",args->volume);
    		gtk_range_set_value(args->slider, args->volume);	
    	}
    //	gtk_range_set_adjustment(GTK_RANGE(args->slider),args->volume);
    //	gtk_scale_set_value_pos(args->slider, args->volume);
    }
     
    static void
    view_popup_menu(GtkWidget *icon, gpointer user_data) {
    	GtkWidget *menu, *menuitem;
     
    	menu = gtk_menu_new();
    	menuitem = gtk_menu_item_new_with_label("Quit");
     
    	g_signal_connect(menuitem, "activate", G_CALLBACK(quit), icon);
     
    	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
    	gtk_widget_show_all(menu);
     
    	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, NULL, NULL);
    }
    /*
    int
    write_volume(const char mixer[], gdouble volume) {
    	int fd_mixer, vol, v;
     
    	if((fd_mixer = open(mixer, O_RDWR)) < 0) {
    		printf("write_volume(): open %s failed !!\n", mixer);
    		perror(mixer);
    		exit(1);
    	}
     
    	v = volume;
    	vol = 10*log((v << 8) | v);
     
    	if(ioctl(fd_mixer, SOUND_MIXER_WRITE_VOLUME, &vol) == -1) 
    		perror("ioctl");
     
    	close(fd_mixer);
    }
    */
    static void
    quit(GtkWidget *icon, gpointer user_data) {
    	gtk_main_quit();
    }
     
    static void
    show_window(GtkWidget *icon, GtkWidget *win) {
    	if(gtk_widget_get_visible(win))
    		gtk_widget_hide(win);
    	else
    		gtk_widget_show_all(win);
    }
     
    static void 
    slider_moved(GtkWidget *range, gpointer user_data) {
    	gdouble pos = gtk_range_get_value(GTK_RANGE(range));
    	//g_print(g_strdup_printf("%d\n", pos));
    	//write_volume(mixer_dev, pos);
    }
     
    int
    get_volume(long *volume) {
    	long minv, maxv;
    	snd_mixer_t *handle;
    	snd_mixer_selem_id_t *sid;
    	const char *card = "default";
    	snd_mixer_elem_t *elem;
     
    	if((snd_mixer_open(&handle, 0)) < 0) {
    		snd_mixer_close(handle);
    		return -1;
    	}
     
    	if((snd_mixer_attach(handle, card)) < 0) {
    		snd_mixer_close(handle);
    		return -2;
    	}
     
    	if((snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
    		snd_mixer_close(handle);
    		return -3;
    	}
     
    	if(snd_mixer_load(handle) < 0) {
    		snd_mixer_close(handle);
    		return -4;
    	}
     
    	snd_mixer_selem_id_alloca(&sid);
    	snd_mixer_selem_id_set_index(sid, 0);
    	snd_mixer_selem_id_set_name(sid, "Master");
     
    	elem = snd_mixer_find_selem(handle, sid);
    	if(!elem) {
    		snd_mixer_close(handle);
    		return -5;
    	}
     
    	snd_mixer_selem_get_playback_volume_range(elem, &minv, &maxv);
    	if(snd_mixer_selem_get_playback_volume(elem, 0, volume) < 0) {
    		snd_mixer_close(handle);
    		return -6;
    	}
    	*volume -= minv;
    	maxv -= minv;
    	minv = 0;
    	*volume = 100 * (*volume) / maxv;
    	snd_mixer_close(handle);
    }
     
    int
    main (int argc, char **argv)  {
    	long volume;
    	GtkWidget *window;
    	GtkScale *slider;
    	GtkAdjustment *adjust;
    	GtkMenu *menu;
    	GtkStatusIcon *tray;
    	GdkRectangle area;
    	struct soundth_args *args = malloc(sizeof(*args));
     
    	get_volume(&volume);
    	get_volume(&(args->volume));
    	args->slider = slider;
     
    	gtk_init(&argc, &argv);
     
    	tray = gtk_status_icon_new_from_file("./vol.png");
    	gtk_status_icon_get_geometry(tray, NULL, &area, NULL);
    	window = gtk_window_new(GTK_WINDOW_POPUP);
    	gtk_window_set_default_size(GTK_WINDOW(window), 40, 150);
    	gtk_window_move(GTK_WINDOW(window), area.x, area.y-160);
     
    	adjust = gtk_adjustment_new(volume, 0, 101, 1, 1, 1);
    	slider = gtk_scale_new(GTK_ORIENTATION_VERTICAL, adjust);
    	gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(slider));
     
    	g_idle_add(sound_thread, args); 
     
    	g_signal_connect(tray, "activate", G_CALLBACK(show_window), window);
    	g_signal_connect(slider, "value-changed", G_CALLBACK(slider_moved), NULL);
    	g_signal_connect(tray, "popup-menu", G_CALLBACK(view_popup_menu), menu);
     
    	gtk_main();
    	free(args);
     
    	return EXIT_SUCCESS;
     
    }
    Merci pour votre aide.

  2. #2
    Membre averti
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    tu pointe sur une structure
    struct soundth_args *args = user_data

    puis tu donne l'adresse du pointeur "slider" tu transmet donc un argument de type : GtkScale **
    &(args->slider)

    le prototype est celui ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gdouble gtk_range_get_value (GtkRange *range);
    et tu l'utilise comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gdouble gtk_range_get_value (GtkRange **range);
    ce qui provoque le segfault car la fonction tente de dereferencer un pointeur pour avoir une donnee et se retrouve avec un pointeur sur cette donnee.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int sound_thread(gpointer user_data) {
    	struct soundth_args *args = user_data;
    	if(get_volume(args->volume) != gtk_range_get_value(GTK_RANGE(&(args->slider)))) {
    ceci devrais convenir, tu peux meme te passer du pointeur args en soi comme ceci : gtk_range_get_value(GTK_RANGE(user_data.slider))

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int sound_thread(gpointer user_data) {
    	struct soundth_args *args = user_data;
    	if(get_volume(args->volume) != gtk_range_get_value(GTK_RANGE(args->slider))) {
    de plus le prototype de g_idle_add est celui ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    guint g_idle_add (GSourceFunc function, gpointer data);
    et tu l'utilise comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    guint g_idle_add (GSourceFunc function, struct soundth_args *args);
    ce qui n'est pas tres plaisant ^^

    gpointer est typedef comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef void* gpointer;
    un petit bypass donnerais ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    g_idle_add (function, (void *) data);
     
    //puis serais recuperer comme cela
     
    int sound_thread(void * user_data) {
    	struct soundth_args *args = (struct soundth_args *)user_data;
    ou si tu prefere
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    g_idle_add (function, (gpointer) data);
     
    //puis serais recuperer comme cela
     
    int sound_thread(gpointer user_data) {
    	struct soundth_args *args = (struct soundth_args *)user_data;

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 52
    Par défaut
    Tout d'abord un grand merci pour ton aide, je m'étais emmelé les pinceaux avec les pointeurs ...

    Le soucis venait en fait de slider que je faisais pointer sur ma structure, mais avant d'initialiser slider en fait. Du coup args->slider pointait sur du vide d'où le segfault.

Discussions similaires

  1. passage par pointeur sur char, propre si possible
    Par wanecque dans le forum C++
    Réponses: 7
    Dernier message: 18/10/2014, 01h22
  2. lire pointeur sur structure en argument
    Par Linu6 dans le forum C
    Réponses: 3
    Dernier message: 23/09/2007, 00h53
  3. Passage des arguments par valeur
    Par mpereg dans le forum Général Python
    Réponses: 4
    Dernier message: 13/03/2007, 17h12
  4. probleme sur le passage d'argument par adresse
    Par ghostdog dans le forum C
    Réponses: 4
    Dernier message: 23/11/2005, 15h50
  5. Passage des arguments par le shell
    Par panda31 dans le forum C
    Réponses: 8
    Dernier message: 09/11/2005, 11h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo