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

GTK+ Discussion :

g_spawn_command_line_sync et g_spawn_sync


Sujet :

GTK+

  1. #1
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut g_spawn_command_line_sync et g_spawn_sync
    Bonjour,

    J'ai souvent le besoin de lancer des processus à partir de mes codes utilisant GTK. Pour ce faire, j'utilise fréquemment g_spawn_command_line_sync() en encapsulant la ligne de commande (avec ses arguments) dans une chaine de caractères, et ça marche bien.

    Voilà qu'aujourd'hui, j'ai besoin de faire la même chose, mais le process que je lance est "bavard" en crachant plein de résultats sur la console dont je n'ai aucune utilité. Je voudrais donc lancer ce process en éteignant ces sorties inutiles (l’équivalent de "> /dev/null" sur linux, ou bien "> NUL" sous Windows). J'ai bien essayé de rajouter justement "> NUL" (je suis sous Windows) dans la chaine lancée, mais ça ne fait rien du tout.

    En creusant la doc de la Glib, j'ai découvert que je pouvais m'en sortir en utilisant plutot g_spawn_sync() (qui est en fait utilisé par g_spawn_command_line_sync()), mais je n'arrive pas à m'en sortir.

    Voici rapidement et très schématiquement ce que je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* la chaine commande (pointeur sur un char) contient l'instruction à lancer avec tout ses arguments */
    char tempo[2][1000];
    (void)strcpy(tempo[0],commande),
    tempo[1][0]='\0';
    g_spawn_sync (NULL,
                         tempo,
                         NULL,
                         G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,
                         NULL,
                         NULL,
                         NULL,
                         NULL,
                         NULL,
                         NULL);
    Le code compile et tourne sans aucun problème ni message d'erreur. En revanche, l'instruction n'est pas lancée (par exemple elle doit créer des fichiers qui ne sont pas créés).

    Ai-je loupé quelque chose ?

    Merci pour toute aide sur ce point.

    Cordialement, Eric.

  2. #2
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Je me réponds à moi-même. Apparemment, le problème est dans le pointeur tempo qui n'est pas du bon type. Pourtant, j'ai bien un char **tempo comme indiqué dans la doc.

    Quelqu'un aurait-il une idée ici ?

    Encore merci pour toute aide sur ce point.

    Cordialement,

    Eric.

  3. #3
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Bonjour,

    un tableau à 2 dimensions et un tableau de pointeurs ce n'est pas tout à fait la même chose. Il faut etre conscient que de la disposition en mémoire des octets est différente.

    Quand tu as un argument qui s'appelle argv, c'est pour imiter le principe du argc, argv utilisé en C pour injecter les arguments en ligne de commande passés à programme dans ton main.

    g_spawn_sync attend un char ** : un pointeur vers des pointeurs de caractères. Tu peux donc passer l'adresse d'un tableau de pointeurs à condition que la dernière valeur du tableau soit à NULL. Cette valeur permet à la fonction appelée de savoir quand elle a atteint la fin du tableau (on appelle cela une sentinelle).

    Le mapping en mémoire donne à peu près ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [adresse1] -> adresse3
    [adresse2] -> NULL
    ...
    [adresse3] -> "argument 1"

    Donc tu peux écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char * tempo[2] = { "argument 1", NULL };
    ou bien:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * tempo[2];
    tempo[0] = (char *)"argument 1"; // le cast permet de dire au compilateur "je sais que ce paramètre devrait être en const, mais je pense que personne n'essaiera de la modifier, donc je prends le risque"
    tempo[1] = NULL;
     
    g_spawn_sync(..., &tempo, ...);
    Le soucis que tu peux rencontrer c'est qu'une chaîne codée en dur est dans une zone mémoire non modifiable. Si le code appelé essaie de modifier les arguments, ça va crasher. Normalement on les met en const, mais ça ne résoudra pas le problème ici: le paramètre attendu par g_spawn_sync n'est pas const. Donc il est sans doute préférable de copier de ta chaîne avec g_strdup, stocker la copie dans ton tableau de pointeurs, puis libérer le tout.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char * tempo[2];
    tempo[0] = g_strdup("argument 1");
    tempo[1] = NULL;
     
    g_spawn_sync(..., &tempo, ...);
     
    g_free(tempo[0]);
    Si tu as de nombreux arguments, tout cela peut être un peu rébarbatif. La GLib te fournit alors g_strfreev, qui te permet de libérer à la fois le tableau de pointeurs et les valeurs contenues, si tout ce beau monde a été alloué dynamiquement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    const size_t n_elements = 2;
    char * tempo[n_elements] = g_malloc(n_elements * sizeof(char *));
    tempo[0] = g_strdup("argument 1");
    tempo[1] = NULL;
     
    g_spawn_sync(..., &tempo, ...);
     
    g_strfreev(&tempo);

  4. #4
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Merci liberforce. Je regarde ceci dès que possible (je suis en déplacement pour une dizaine de jours). Non, je n'utilise pas (ici) d'allocation dynamique.

    Je ne manquerai pas de donner l'issue de ces essais ici.

    Encore merci.

    Cordialement, Eric.

  5. #5
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    En tout cas c'est un problème purement de C, GTK+ n'intervient pas là dedans. Tu pourras sans doute avoir des précisions sur le forum C si besoin.


    Encore merci.
    À ton service

  6. #6
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    liberforce,

    Comme annoncé ici, je suis de retour de déplacement, et reprends ce problème. Après quelques essais, je suis arrivé à faire fonctionner g_spawn_sync() dans le contexte qui m'interessait, avec plusieurs arguments (variables) sur la ligne de commande à lancer.

    Merci infiniment pour ton aide.

    Je passe ce post en résolu.

    Eric.

+ Répondre à la discussion
Cette discussion est résolue.

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