Forum Programmation.c Shell script-->langage C

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
-6
22
nov.
2015

Bonjour
j'ai besoin d'aide concernant ce programme…je veux le traduire en langage C, merci d'avance.

The Shell script to blink the LED is given as follows
// Blink an LED on breadboard
//PIN="26" # P8_6is gpio1_3 = (32 * 1) + 3 = 35

GPIOPIN="/sys/class/gpio/gpio$PIN"
if [ -d "$GPIOPIN" ]; then
echo "Blinking LED connected to Pin $PIN …"
else
echo $PIN > /sys/class/gpio/export

echo "Blinking LED connected to Pin $PIN …"
sleep 1
fi
while true; do
echo high > $GPIOPIN/direction
sleep 2
echo low > $GPIOPIN/direction
sleep 2
done

fclose(duty);
fclose(period);
fclose(run);

return 0;
}

  • # question pas très élégante

    Posté par  . Évalué à 1.

    alors voici une réponse pas très élégante : bonne lecture

    # Du code avec coloration syntaxique
    #include <QFile>
    #include <syslog.h>
    
    #ifndef QT_NO_DEBUG
      #define BASE_SYSFS "/tmp"
    #else
      #define BASE_SYSFS ""
    #endif
    int write(const QString &filename, const QString &message);
    int readyGPIO(int number, QFile &file, bool readOnly)
    {
      //http://falsinsoft.blogspot.fr/2012/11/access-gpio-from-linux-user-space.html
      //echo XX > /sys/class/gpio/export
      //echo "out" > /sys/class/gpio/gpioXX/direction
      //echo 1 > /sys/class/gpio/gpioXX/value
      //cat /sys/class/gpio/gpioXX/value
      int result = write(BASE_SYSFS "/sys/class/gpio/export", QString::number(number));
      if (result == EXIT_FAILURE)
        return result;
    
      result = write(BASE_SYSFS "/sys/class/gpio/gpio"+QString::number(number)+"/direction"
                     , readOnly ? "in" : "out");
      if (result == EXIT_FAILURE)
        return result;
    
    #ifndef QT_NO_DEBUG
      if (file.isOpen())//should not be necessary but ...
        {
          syslog(LOG_WARNING, QObject::tr("[WARNING][%1:%2] %3: Internal error ! Please report it !")
                 .arg(__LINE__)
                 .arg(__FILE__)
                 .arg(__FUNCTION__)
                 .toUtf8().data());
          file.close();
        }
    #endif
      file.setFileName(BASE_SYSFS "/sys/class/gpio/gpio"+QString::number(number)+"/value");
      if (readOnly)
        result = file.open(QIODevice::ReadOnly);
      else
        result = file.open(QIODevice::WriteOnly);
      if (!result)
        {
          syslog(LOG_ERR, QObject::tr("[ERROR][%1:%2] %3: Couldn't achieve to open %4 in %5 ! Here the error message: %6")
                 .arg(__LINE__)
                 .arg(__FILE__)
                 .arg(__FUNCTION__)
                 .arg(file.fileName())
                 .arg(readOnly ? "read_only" : "write_only")
                 .toUtf8().data());
          return EXIT_FAILURE;
        }
      return EXIT_SUCCESS;
    }
    int closeGPIO(int number, QFile &file)
    {
      int result;
      file.close();
      result = write(BASE_SYSFS "/sys/class/gpio/unexport", QString::number(number));
      if (result == EXIT_FAILURE)
        return result;
    
      return EXIT_SUCCESS;
    }
    
    int write(const QString &filename, const QString &message)
    {
      int result;
      QFile tmp;
      QByteArray msg = message.toUtf8().data();
      tmp.setFileName(filename);
      if (!tmp.open(QIODevice::WriteOnly))
        {
          syslog(LOG_ERR, QObject::tr("[CRITICAL][%1:%2] %3: Impossible to open %4 ! Here is the error message: %5")
                 .arg(__LINE__)
                 .arg(__FILE__)
                 .arg(__FUNCTION__)
                 .arg(filename)
                 .arg(tmp.errorString())
                 .toUtf8().data());
          return EXIT_FAILURE;
        }
      result = tmp.write(msg);
      if (result != msg.size() || !tmp.flush())
        {
          syslog(LOG_ERR, QObject::tr("[CRITICAL][%1:%2] %3: Impossible to write >%4< into %5 ! Here is the error message: %6")
                 .arg(__LINE__)
                 .arg(__FILE__)
                 .arg(__FUNCTION__)
                 .arg(QString(msg))
                 .arg(filename)
                 .arg(tmp.errorString())
                 .toUtf8().data());
          return EXIT_FAILURE;
        }
      tmp.close();
      return EXIT_SUCCESS;
    }
    • [^] # Re: question pas très élégante

      Posté par  . Évalué à 1.

      Bonjour,

      Pourquoi dépendre de QT pour un problème qui est purement Posix ?
      Il suffit d'utiliser les fonctions standard d'ouverture/écriture sur les fichiers.

      Bon, je critique mais j'ai la flegme de construire un exemple.
      Voici un lien qui montre des bouts de code:
      http://falsinsoft.blogspot.fr/2012/11/access-gpio-from-linux-user-space.html

      • [^] # Re: question pas très élégante

        Posté par  . Évalué à 1.

        Merci de prendre le lien de lire mon post :
        - je dis que je ne me fatigue pas à expliquer car le gars ne se fatigue pas à faire une vraie demande;
        - tu poste un lien que j'ai également dans ma réponse (puisque dans mon code j'ai l'habitude d'indiquer mes sources d'infos).

        Et pour finir : je ne lui ai pas fait un code pour son problème, je lui ai copier un de mes codes pour qu'il ait une idée de quoi faire. Ensuite à lui de faire le travail.

        P.S. : Et la raison pour laquelle j'ai été "inutilé" m'échappe totalement car je donne une piste (avec du code opérationnel), et que la seule autre réponse apportée n'apporte rien.

        • [^] # Re: question pas très élégante

          Posté par  (site web personnel) . Évalué à 2.

          P.S. : Et la raison pour laquelle j'ai été "inutilé" m'échappe totalement car je donne une piste (avec du code opérationnel), et que la seule autre réponse apportée n'apporte rien.

          En dépit de ta bienveillance, tu tapes un peu à côté car tu proposes du code C++ et pas du C. Cela pourrait expliquer quelques moinsages.

          • [^] # Re: question pas très élégante

            Posté par  . Évalué à 1.

            j'veux bien, mais pour avoir une certaine expérience dans les deux langages (ce sont les seuls que j'utilise, à part sporadiquement ceux du web ; je fais donc régulièrement du code C only), en quoi mon code est réellement C++ dépendant ?

            Donc pour ce qui est de ce code, si on enlève Qt alors tout marche parfaitement en C.

            Donc en quoi je tape à côté ?

            Je t'avoue être quelque peu vexé (ouais puéril, toussa toussa) et préfère donc ne plus répondre sur les forums (et donc même aller y jeter un oeil) : linuxfr n'y perd pas grand chose ou rien, et moi j'évite de perdre mon temps.

            Ciao.

            P.S. :
            - j'avoue ne pas savoir pourquoi cela m'énerve, j'connais le ternet pourtant ; il y a des jours comme ça.
            - allez-y "inutiler" !!

            • [^] # Re: question pas très élégante

              Posté par  (site web personnel) . Évalué à 2.

              Donc pour ce qui est de ce code, si on enlève Qt alors tout marche parfaitement en C.

              Je te crois sur parole, cependant ça reste du C++ et l'OP demande du C — et vu la question cela m'étonnerait qu'il soit assez autonome pour faire la traduction tout seul.

              Ensuite si tu veux savoir précisément pourquoi les gens ont moinssé, il faudra attendre que les moinsseurs répondent eux-même à ta question! ☺

              Je t'avoue être quelque peu vexé (ouais puéril, toussa toussa)

              Boh alors? Qu'est-ce qui t'arrive? ☺ Qu'est-ce qu'il a de vexant dans cette affaire?

              • [^] # Re: question pas très élégante

                Posté par  . Évalué à 3.

                • sur ma réponse Ma réponse était du niveau de la question : il doit faire ses devoirs ; et je crois bien que l'on commence à apprendre à coder réellement qu'en regardant le code des autres. Une réponse "nettoyée" du "C++" n'aurait pas fait progresser le gars.

                Je crois donc avoir été pertinent (tant sur le code -qui répond à la question car c'est du C[2]), que sur la forme qui se voulait pédagogique (il aurait eu du travail à fournir). De plus je crois avoir mis du code qui lui permettait de voir un peu :
                - la gestion des erreurs;
                - la gestion des logs.
                - l'écriture de fonctions lisibles

                Et pour finir même si l'on considère que ce C++ n'est pas du C, cela fait avancer le schmilblick puisque c'est plus proche du C que le bash.

                • Sur le pourquoi je suis vexé. Pas clair le pourquoi. Ce qui est sûr c'est que sur les forums contrairement aux journaux on ne cherche pas à s'exprimer mais à aider, et bien "moinser" une aide[1] j'avoue que cela me dépasse un peu.

                [1] d'autant plus si (liste avec OU logique) :
                - les moinsseurs n'apportent rien,
                - ne comprennent pas suffisamment le C/C++ pour voir que la réponse est pertinente

                [2]la notation file.open(..) marche parfaitement en C ; les seules choses spécifiques sont
                - QObject::.
                - la notion de référence

                • [^] # Re: question pas très élégante

                  Posté par  . Évalué à 1.

                  Désolé sur la forme.

                  J'ai après post bataillé, mais -peut-être un timer ?- je me suis pris un "vous ne passerez pas".
                  Et je ne parviens toujours pas à avoir une forme correcte ; pas doué et pas l'habitude.
                  Voici le texte plus correcte :

                  ************** sur ma réponse ************
                  Ma réponse était du niveau de la question : il doit faire ses devoirs ; et je crois bien que l'on commence à apprendre à coder réellement qu'en regardant le code des autres. Une réponse "nettoyée" du "C++" n'aurait pas fait progresser le gars.
                  
                  Je crois donc avoir été pertinent (tant sur le code -qui répond à la question car c'est du C[2]), que sur la forme qui se voulait pédagogique (il aurait eu du travail à fournir). De plus je crois avoir mis du code qui lui permettait de voir un peu :  
                    * la gestion des erreurs;
                    * la gestion des logs.
                    * l'écriture de fonctions lisibles
                  
                  Et pour finir même si l'on considère que ce C++ n'est pas du C, cela fait avancer le schmilblick puisque c'est plus proche du C que le bash.  
                  
                  ************** Sur le pourquoi je suis vexé. ********
                  Pas clair le pourquoi. Ce qui est sûr c'est que sur les forums contrairement aux journaux on ne cherche pas à s'exprimer mais à aider, et bien "moinser" une aide[1] j'avoue que cela me dépasse un peu.
                  
                  [1] d'autant plus si (liste avec OU logique) :
                  - les moinsseurs n'apportent rien,
                  - ne comprennent pas suffisamment le C/C++ pour voir que la réponse est pertinente
                  
                  [2]la notation file.open(..) marche parfaitement en C ; les seules choses spécifiques sont
                  - QObject::.
                  - la notion de référence
                  • [^] # Re: question pas très élégante

                    Posté par  . Évalué à 3.

                    Alors je précise que je n'ai même pas moinssé.

                    Mon propos était plus sur le fond: les outils les plus simples pour un problème donné sont à privilégier ; c'est mon avis. C'est un bête problème de lecture/écriture de fichiers et répertoires, sur un problème spécifique à linux et en C, donc QT ne me parait pas adapté, y compris pédagogiquement.

                    Désolé, pour avoir voulu défendre cette position, avoir créé un (petit) champ de bataille et tant d'embarras, mais bon, on peut bien donner son avis..

                    • [^] # Re: question pas très élégante

                      Posté par  . Évalué à 1.

                      Le "champ de bataille" n'était pas sur ta réponse[1] mais sur sur le fait que ma réponse ait été "moinssée".

                      Donc oui tu peux donner ton avis, et je garderai bien d'empêcher qui que ce soit de donner son avis.

                      [1] qui encore une fois n'apportait rien du tout à mon post initial ; mon post avait le mérite d'apporter un code qui fonctionnait et qui montrait/expliquait comment faire ce qu'il désirait (suffisait de lire). Pour le reste il faut lire mes réponses précédentes.

                      P.S. : pour ce qui est du côté pédagogique de ma réponse, je ne partage pas ton opinion.

      • [^] # Re: question pas très élégante

        Posté par  . Évalué à 1.

        merci beaucoup

  • # Qu'est-ce qui te bloque?

    Posté par  (site web personnel) . Évalué à 4.

    Si tu veux obtenir de l'aide, c'est bien de montrer ce que tu as essayé. Qu'est-ce qui coince? Je ne vois que des entrées-sorties pas très compliquées, donc si tu ne nommes pas de problème précis, tout le monde va croire que tu veux laisser quelqu'un d'autre faire tes devoirs à ta place!

    • [^] # Re: Qu'est-ce qui te bloque?

      Posté par  . Évalué à 1.

      bonjour
      voila ce que j'ai essayé:
      int main()
      {
      int p; char tab[max_N];
      int gpio = 26;
      p=open("/sys/class/gpio/export", O_WRONLY);
      sprintf(tab, "%d", gpio);
      write(p, tab, strlen(tab));
      close(p);
      sprintf(tab, "/sys/class/gpio/gpio%d/direction", gpio);
      p = open(tab, O_WRONLY);
      write(p, "out", 1);
      write(p, "in", 3);
      close(p);
      if [ -d "$GPIOPIN" ] then
      fprintf ("Blinking LED connected to Pin $PIN …")
      else
      // echo $PIN > /sys/class/gpio/export

      fprintf("Blinking LED connected to Pin $PIN …")
      //sleep 1
      else
      while (true) do
      {
      sprintf(tab, "/sys/class/gpio/gpio%d/value", gpio);
      p = open(tab, O_WRONLY);
      write(p, "1", 1);

      write(p, "0", 1);
      close(p);
      return 0;
      }

      • [^] # Re: Qu'est-ce qui te bloque?

        Posté par  . Évalué à 1.

        Tu ne maîtrise pas du tout le C semble-t-il (fprintf, point virgule, le code ne compile pas), et probablement pas la programmation (la logique).

        À mon avis, tu ferais mieux de te tourner sur du python (ilm y a des exemples disponibles), ou faire/refaire des exos/algos.

        Pourquoi ne pas utiliser le bash ou le python ? Tu t'éviteras des heures de débogage, et tu investiras "utile" (je suppose que tu vas faire d'autres choses, et qu'également tu chercheras à le faire en C).
        Si tu veux faire cela en C pour apprendre le C, alors il te faut faire des exos intermédiaires.

        Pour ce qui est d'une piste, teste ceci :

        while (1) do
        {
        printf("TOTO\n");
        return 0;
        }

        • [^] # Re: Qu'est-ce qui te bloque?

          Posté par  . Évalué à 1.

          Tu ne maîtrise pas du tout le C semble-t-il

          J'imagine que s'il le maîtrisait, il ne viendrait pas poser de questions du coup, non ?

          (Ou bien c'est encore un chinois du FBI ??)

      • [^] # Re: Qu'est-ce qui te bloque?

        Posté par  . Évalué à 1. Dernière modification le 23 novembre 2015 à 14:45.

        C'est bon début !

         /* charge les déclarations de fopen,fclose,fprintf */
        #include <stdio.h>
        

        Tu rajouteras ici aussi les autres entêtes pour stat() et cie, cf. suite.
        Aussi stdlib.h pour utiliser exit() dans la gestion des erreurs…

        int main()
        {
        int p; char tab[max_N];

        max_N ?
        1) c'est une définition non standard
        2) admettons que cela équivaut à INT_MAX ou autre provenant de /usr/include/limits.h,
        tu risque au pire d'allouer beaucoup de mémoire sur la pile pour rien, au mieux d'exploser la pile directement…
        Tu pourrais utiliser PATH_MAX, mais bon essayons de calculer au plus juste :

        #define GPIO_DIRECTORY_FORMAT "/sys/class/gpio/gpio%d/"
        /* Cela marche jusqu'à gpio <= 99 */
        /* invariant: strlen("direction") > strlen("value"), cf. plusbàs */
        char tab[sizeof(GPIO_DIRECTORY_FORMAT)+sizeof("direction")]
        

        int gpio = 26;
        p=open("/sys/class/gpio/export", O_WRONLY);
        sprintf(tab, "%d", gpio);
        write(p, tab, strlen(tab));
        close(p);

        On peut remplacer write par fprintf, pas besoin de créer une chaîne temporaire du coup. Cela devient:

        FILE *f = fopen("/sys...", O_WRONLY);
        fprintf(f,"%d", gpio);
        fclose(f);
        

        sprintf(tab, "/sys/class/gpio/gpio%d/direction", gpio);

        Toujours éviter les fonctions de formatage et d'io qui ne sont non-bornées pour éviter un dépassement de tampon.

        -> snprintf(tab,sizeof(tab), GPIO_DIRECTORY_FORMAT "direction", gpio);

        p = open(tab, O_WRONLY);
        write(p, "out", 1);

        le 1 n'est pas bon…

        write(p, "in", 3);
        close(p);

        Idem j'utiliserais plustôt le IO haut niveau, open -> fopen, write -> fputs/fprintf.

        if [ -d "$GPIOPIN" ] then

        devient:

        #include <sys/types.h>
        #include <sys/stat.h>
        #include <unistd.h>
        
        struct stat sb;
        if (0 != stat("....", &sb)) {
          /* traiter l'erreure... */
        }
        
        if ((sb.mode & S_IFMT) == S_IFREG) {
        

        fprintf ("Blinking LED connected to Pin $PIN …")

        fprintf -> printf ou fprint(stdout,...)
        }
        else {
        

        else
        // echo $PIN > /sys/class/gpio/export

        Idem, couple fopen, fprintf/fputs, fclose…

        fprintf("Blinking LED connected to Pin $PIN …")
        idem, fprintf prent un FILE* comme premier argument, printf utilise stdout implicitement.

        //sleep 1
        usleep () ???

        else

        Utilise systématiquement des accolades quand tu imbriques les instructions de contrôles, cela est plus lisible et moins sujet à se tromper.

        while (true) do
        {

        sprintf(tab, "/sys/class/gpio/gpio%d/value", gpio);

        Déplace cela hors de la boucle, pas besoin de recalculer le chemin à chaque itération
        -> snprintf(tab,sizeof(tab), GPIO_DIRECTORY_FORMAT "/value", gpio);

        p = open(tab, O_WRONLY);
        write(p, "1", 1);

        write(p, "0", 1);
        close(p);

        ok

        return 0;
        }

        Pour apprendre, rien de mieux que de consulter les manpages de toutes les fonctions/headers mentionnés précedemment.
        genre sur manpages.debian.net ou sur ton système (man 2 xx ou man 3 xx).

        • [^] # Re: Qu'est-ce qui te bloque?

          Posté par  . Évalué à 1.

          Il faut changer le /* Cela marche jusqu'à gpio <= 99 */ par 999, car on compte deux fois un charactère '\0'… bref :)

          L'important à retenir c'est que même si l'on se plante dans le calcul, ben le code ne risque pas de se planter trop violemment car après on utilise sizeof() sur l'objet construit et snprintf tronquera toujours avec un \0 (sauf si size = 0).

        • [^] # Re: Qu'est-ce qui te bloque?

          Posté par  . Évalué à -2.

          merci beaucoup :)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.