Forum Programmation.c Macro pour définir identifiant uniques

Posté par  (site web personnel) .
Étiquettes : aucune
0
12
mai
2009
Bonjour,

je suis devant un problème àlc... J'ai un fichier en C sur lequel le cpp va passer plusieurs fois pour créer plusieurs version du code. Genre gcc -E test.c > v1.c && gcc -E test.c > v2.c , etc etc
Au final, je vais tout lier ensemble, et ça bloque à cause de définitions multiples de certains symboles. Je ne peux pas utiliser 'static' pour éviter ça :( Je ne peux pas définir de macro en cli (en utilisant -D), les fichiers doivent utiliser la même commande exactement.

Du coup, je pensais qu'il serait possible d'avoir une macro qui s'étend en qqch d'unique à chacune des invocations et qui soit utilisable dans un identifiant. Il y a bien des macros qui donnent l'heure/date d'invocation, mais pas utilisable dans un identifiant C. Je n'ai pas trouvé de macro du type __RANDOM__. Le truc qui s'en rapprochait le plus, c'est __COUNTER__, mais il commence à 0 à chaque invocation, et en plus, comme j'ai besoin d'avoir le nom à 2 endroits dans le fichiers, ça ne marche pas correctement (j'ai une fois "toto0" puis "toto1"... classique quoi).

La force n'est pas avec moi ce matin :(
  • # pas compris l'interet

    Posté par  . Évalué à 7.

    compiler le meme fichier .c plusieurs fois => plusieurs .o
    puis lier l'ensemble (alors que chaque fichier fait la meme chose)

    on peut m'expliquer l'interet ?

    mes cours de C remonte à longtemps, mais j'ai pas souvenir que cela apportait quelques choses.
    • [^] # Re: pas compris l'interet

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

      j'ai simplifié... Je travaille avec un canevas à composant. Chaque composant peut être vu comme une classe si tu veux, et un compilateur prend ça et va créer un code spécifique pour chaque instance de composant. Si vraiment tu veux des détails, je peux t'en donner autant que tu veux, mais c'est pas trop la question ici.

      Si tes cours de C remontent à longtemps, peut être que tu devrais prendre plus de précautions avant de ne pas répondre à la question posée et mettre en doute l'intérêt de la chose.

      Marc
    • [^] # Re: pas compris l'interet

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

      puisque visiblement, ce commentaire fort sympathique passe à 6, je me dis que j'ai peut être mal formulé quelques chose. Néanmoins, dans mon message initial, il est bien indiqué:
      "le cpp va passer plusieurs fois pour créer plusieurs version du code."

      Donc, en sortie, j'ai bien des sources différents. Il faut penser au fichier original comme un template. Bref.
      • [^] # Re: pas compris l'interet

        Posté par  . Évalué à 3.

        comment penses-tu faire pour connaitre le nom des fonctions ou des variables qui seront utilisées dans chacun de tes .c ?

        ne vaudrait-il pas mieux faire une copie du fichier original
        puis un sed ou awk pour rechercher/remplacer les instances de ta variable ?
        tout ca dans un script qui te generera N instance de ton template
        mais dont tu connaitras au moins les noms des variables et des fonctions...

        sinon il faut peut-etre faire de la programmation objet
        du coup tu definis une classe avec les fonctions elementaires
        puis tes instances sont des derivées de cette classe elemenataire
        • [^] # Re: pas compris l'interet

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

          Là on s'écarte un peu de ma question initiale, mais pas grave ;)
          Le compilateur (qui prend entre autres, des fichiers C en entrée et produit du C en sortie) est relativement "complexe". Par complexe, c'est juste que c'est pas un script de 10 lignes de bash. C'est une application assez lourde, écrite en Java avec un fw à composant. Du coup, intégrer du sed/awk dedans, pas possible (d'autant plus qu'il doit fonctionner sur autre chose que des unix, windows en particulier, et dépendre de cygwin & cie, bof bof).

          Pour détailler un peu plus, le code C va être intégralement analyser pour construire un ASG. ASG qui est manipulé pour effectuer différentes taches:
          - créer un code partagé par plusieurs instances d'un même composants. Ca va demander de faire des structure pour stocker les données d'instances et potentiellement modifier le code donné en entrée pour utiliser cette structure.
          - optimisation du code produit (fortement dépendant de l'architecture que tu compiles... est-ce que tu peux changer les composants à chaud ? Certaines liaisons peuvent elles changer ?)
          - etc

          Du coup, la manip du code n'est pas vraiment simple. Parfois, on aimerait bien faire certaines chose pas très bien, comme c'est le cas pour moi. Je fais une hypothèse sur le code produit, et je m'en sers pour écrire le code d'entrée. C'est mal, mais dans certains cas, on a pas trop le choix. En l'occurrence ici, j'aimerais que certaines fonctions dans le code final généré reflète des noms qui sont données dans le langage qui décrit l'architecture du système.

          On se concentre sur du code en C (pour plein de raisons, mais la plus grande étant les cibles qu'on vise n'ont pas toujours un compilateur C++, et il est plus facile de maîtriser ce qui fini sur ta plate-forme en utilisant du C qu'autre chose. J'ai pas dit que c'était une vérité absolue, mais parfois, faut faire des choix pragmatique pour arriver à quelque chose qui fonctionne), du coup, l'utilisation d'un langage OO n'est pas possible. On a des travaux visant à intégrer des composants écris en C++, on sait récupérer du code objet, etc.

          Et pour finir, la question était aussi pour nourrir ma curiosité, car je suis souvent surpris par ce qu'on peut faire avec les macros et le cpp, et je pensais qu'ici, j'aurais le plus de chance de trouver des as de ce dialecte. J'avoue avoir été un peu déçu d'avoir comme réponse:
          "j'ai pas fait de C depuis des lustres, mais ça sert à rien ce que tu fais"
          "projet sponso par orange, normal que ça soit de la merde"
          • [^] # Re: pas compris l'interet

            Posté par  . Évalué à 3.

            Bah d'un côté, t'as un projet basé sur une architecture bancale, avec des contraintes que je trouve très étranges, avec des gens prenant des décisions "pragmatiques" (c-à-d le projet est fait à l'arrache), et en plus tout ça dirigé par Orange (enfin, FT) bien connu pour ses projets efficaces et bien faits.

            Bref, tu peux peut-être dire que tu es un incompris, mais là franchement si il y a quelqu'un qui arrive à trouver une solution à ce merdier (je juge peut-être un peu vite, mais vu tes explications ...(d'ailleurs j'ai pas tout compris ...)) je lui souhaite bon courage !

            PS: je fais du C depuis presque 10 ans.
            • [^] # Re: pas compris l'interet

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

              "une architecture bancale"

              Peux tu développer ?

              "contraintes que je trouve très étranges"

              De quelles contraintes tu parles ?

              "le projet est fait à l'arrache"

              Sur quoi tu te bases pour dire ça ? J'ai rarement vu comme définition de pragmatique : à l'arrache. Le choix du langage C pour quand tu vises des micro contrôleurs 8bits avec qqs KiB de RAM, ça me semble pas très surprenant non plus et c'est là que tu trouvera le plus de doc et de code.

              "Orange (enfin, FT) bien connu pour ses projets efficaces et bien faits"

              Peux tu cités les projets issus de Orange Labs (FT R&D) auxquels tu penses ? De plus, si tu avais pris 5min pour regarder, tu aurais vu que Orange est le principal acteur du projet, mais pas le seul.

              Tu m'excuses, mais soit tu cherches juste à troller, soit t'es un peu à côté de la plaque. J'imagine que c'est la première solution.
              • [^] # Re: pas compris l'interet

                Posté par  . Évalué à 4.

                - Une archi bancale : prendre le même source pour générer plusieurs autres un peu différents, qu'on va assembler ensemble après .... j'ai jamais vu ça et je trouve que c'est _très_ bancal.

                - Contraintes étranges : pas de define en ligne de commande, pas de static, bref on peut toucher à rien ; c'est pour un concours de contraintes ?

                - Fait à l'arrache : vu comme t'es obligé de bidouiller ("Je fais une hypothèse sur le code produit, et je m'en sers pour écrire le code d'entrée."), et le fait même que tu bidouilles, c'est pas le signe d'un projet bien fait. Bon ok, ce genre de trucs crades peuvent se trouver partout ... Sinon, pour le mot "pragmatique", je suis peut-être un peu trop extrême mais aujourd'hui tellement de gens ont déformé sa signification initiale que maintenant dès que quelqu'un l'utilise je le classe dans la catégorie "gros con".

                - Pour Orange : bah au hasard ELSE, où ils ont réinventé la roue, mais comme ça prend du temps, bah il ont fait ça très vite et à l'arrache. Et en plus, le projet n'a mené à rien, il a été abandonné après 1 an.

                Sinon, oui, je cherche effectivement à troller un peu ...
                • [^] # Re: pas compris l'interet

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

                  "Une archi bancale : prendre le même source pour générer plusieurs autres un peu différents, qu'on va assembler ensemble après .... j'ai jamais vu ça et je trouve que c'est _très_ bancal."

                  as tu déjà regardé comment fonctionne un compilateur? Quand tu codes avec les templates C++, tu crois pas que pendant une phase de compil ton template ne vas pas être spécialisé suivant les types dont tu te sers pour le configurer ? Moi je pense que si. C'est la même idée. Ou prend du C++ pour lequel tu ne veux pas payer le prix d'un pointeur vers les metadata, tu vas être obligé de spécialiser le code pour chaque instance.

                  "- Contraintes étranges : pas de define en ligne de commande, pas de static, bref on peut toucher à rien ; c'est pour un concours de contraintes ?"

                  Biensûr que tu peux mettre spécifier des macro au cas par cas, c'est d'ailleurs ce que j'ai fini par faire. Mais de manière général, ces macros ne devraient être utiliser pour piloter la compilation du code

                  "Fait à l'arrache : vu comme t'es obligé de bidouiller" : mon utilisation oui. Je vais pas te raconter ma vie, mais j'ai besoin de faire un truc rapidement, un prototype. Aucun rapport avec le projet. Je peux faire un truc dégueux en C, ça ne dit rien sur le compilateur que j'utilise. Si ? Par exemple, et ça arrive souvent, tu regardes ce que crache gcc au niveau asm, et dans ton code C tu vas aller jouer avec des pointeurs relatif sur la pile écrit en dur. C'est crade, c'est fragile. Mais si le but est juste de faire un proto, une preuve de concept. En aucun cas je peux dire que gcc est "fait à l'arrache".

                  "Pour Orange : bah au hasard ELSE,". Ok. Donc tu connais un projet dont tu n'es pas content, et t'en déduis que tous les projets où orange intervient sont mal gérés ?

                  Tu sais, si c'est le mot orange qui te file des boutons, c'est ton droit. Je ne suis pas payé par Orange, je le prendrai pas personnelement. Par contre, quand tu veux argumenter sur des points techniques, ça serait bien de faire plus que du troll. Quand je te demande qu'est ce qui est bancal, ta réponse est juste de pointer du doigt un élément, sans dire autre chose que "je trouve ça bancal".

                  Pour le reste, je vais en rester là. Si tu es curieux, je t'invite quand même à aller regarder comment ça fonctionne. Y'a du bon et du moins bon. C'est un projet de recherche, pas de la prod. En plus, ça t'évitera d'avoir des avis un peu trop tranché rapidement.

                  Bonne fin de journée
                  • [^] # Re: pas compris l'interet

                    Posté par  . Évalué à 2.

                    Le coup des templates, c'est sympa quand tu codes un compilo, mais quand tu le fais à la main, t'as intérêt à être super balèze pour arriver à faire un truc correct. Les indications que tu donnes montre bien que la plateforme n'est pas encore tout à fait au point ...

                    Pour le fait à l'arrache, OK, tu fais un proto, mais t'admets que tu le fais à l'arrache.

                    Et pour Orange, le projet dont je parle c'est celui que je connais personnellement, mais je connais quelques personnes qui ont bossé chez eux pour d'autres projet (je viens de Rennes, où FT R&D dicte la politique des boites de prestas) et c'est du même genre.

                    Pour les points techniques, je donne des avis qui sont certes des jugements personnels appuyés par des "impressions" que j'ai, mais tu voudrais que je dise quoi ? Quand tu donnes ton avis, c'est un jugement que tu as par rapport aux expériences que tu as eu et en comparant à ce que tu connais.

                    Je ne savais pas que c'était un projet de recherche, je comprend mieux pourquoi c'est un peu pas très propre. Mais aux vues des réponses que tu as eu, tu dois bien voir que cette approche ne paraît pas être ce qu'il y a de plus idéal.

                    Désolé de ne pas avoir pu apporter de réponses à ton problème, et bonne nuit aussi.
                    • [^] # Re: pas compris l'interet

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

                      "Le coup des templates, c'est sympa quand tu codes un compilo, mais quand tu le fais à la main, t'as intérêt à être super balèze pour arriver à faire un truc correct. Les indications que tu donnes montre bien que la plate-forme n'est pas encore tout à fait au point ..."

                      Je t'ai donné un exemple avec les templates. Pour notre utilisation, ce que nous faisons marche relativement bien. Bien sûr, tout n'est pas parfait, surtout quand il faut jouer avec du C dont la grammaire est toufu et souvent étendu par chaque compilateur. Un projet qui a la base est de la recherche n'a pas vraiment vocation à "être au point". Si on désire obtenir un truc qui "est au point" et clean, on ne demande pas à des thésards & cie d'écrire le code, on demande à des développeurs dont c'est le travail.

                      "Pour le fait à l'arrache, OK, tu fais un proto, mais t'admets que tu le fais à l'arrache."

                      Pour être plus précis, je fais un proto qui étend le compilateur Think de base. Je ne suis pas presta, je suis simple thésard, et la qualité du code, même si c'est une qualité en soit, ça n'est pas du tout un résultat de recherche. Un proto qui marche oui, car il permet d'illustrer une méthode. Dans ce cadre, "fait à l'arrache" n'est pas un problème vis à vis du résultat. Ça risque d'être un problème si tu comptes en faire autre chose après.

                      "mais tu voudrais que je dise quoi ? "
                      Il est tout à fait possible de faire passer ses idées sans commencer par des attaques qui n'ont aucun rapport (tu remarquera que je n'ai pas relevé ton attaque où tu me dis clairement que tu me prends pour un con), cf ton premier message sur orange, cf ton 2ème message où tu ne donnes aucun argument, juste des (je raccourcis, mais tu m'accordera que c'était l'idée) "c'est complètement con ce que tu fais". En fait, en étant plus diplomate, les idées passent même souvent mieux. Surtout quand visiblement, on ne connaît ni les buts, ni le contexte, juste en se basant sur une question n'ayant aucun rapport avec le projet.

                      Concernant ELSE, je connais aussi ce projet, j'ai utilisé un peu (FTinux & cie). Je t'avoue que je n'ai jamais vraiment compris l'intérêt du projet. Ça n'enlève rien aux autres projets, qui même s'ils ont un tampon 'Orange' ne sont pas forcément pilotés par les même personnes. Le projet Think a des rapports avec plusieurs autres entreprise du bassin Grenoblois, commence à faire son apparition dans quelques cours à l'université, etc. C'est du logiciel libre, 99,99% du dev se fait sur le svn hébergé par le consortium OW2. Plusieurs laboratoires de recherche (à l'INRIA, à l'INPG/UJF, univ de Pau, sans doute d'autres dont j'oublie le nom) utilise ces outils.
                      Le projet est suffisamment mature pour être utilisé comme tel (sans avoir à mettre les mains dans le cambouis). Voir par exemple le proto ayant été développé dans le cadre d'une thèse: http://senseandsensitivity.rd.francetelecom.com/ .

                      Bref. Tout ça pour dire que je t'avais trouvé très rapide pour décrété qu'un projet dans son ensemble était bancal et mal fichu. Certains points le sont, je suis pas le dernier à le dire. Mais dans l'ensemble, le résultat n'est pas si mal.
                      • [^] # Re: pas compris l'interet

                        Posté par  . Évalué à 2.

                        Bon, au final, c'est un projet de recherche qui n'est pas fait pour être "propre", mais tu t'évertues à dire à ceux qui te répondent que ta démarche est bien fondée, et que tu pensais trouver des bêtes des macros ici, et que t'es déçu. Et tu n'acceptes pas les critiques ?

                        Pour l'attaque, OK, excuse moi, ce n'était pas très malin, mais au départ j'ai réagi sur ce thread après avoir vu ton premier message au ton condescendant et le fait que ça vienne (entre autres) de chez Orange, et je me suis dis que j'allais rentrer dedans ...

                        Pour les projets Orange, tant mieux que le votre marche bien. Je trollais peut-être un peu stérilement, mais quand je pense par exemple au suivi conso sur iPhone qui attend dans les bacs depuis 1 an et demi, je ne peut m'empêcher de pouffer de rire (là, c'est pas à cause des devs, mais de l'orga, du marketing, ...)
  • # option -D

    Posté par  . Évalué à 3.

    sur la ligne de compilation -Dplop=toto
    et dans ton code
    gcc -D PLOP=' "ploap" ' test.c -o test

    et dans ton code
    #define CLE_UNIQUE PLOP

    bien mettre le -D avant le nom de fichier

    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: option -D

      Posté par  . Évalué à 2.

      l'autre solution, est de faire un fichier all.c
      qui se sert de COUNTER
      faire un
      #define ID COUNTER
      et faire des

      #include "fich.c"
      #include "fich.c"
      #include "fich.c"

      l'avantage c'est que la ligne de compilation est bien plus simple ;)

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

      • [^] # Re: option -D

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

        là ça demande de changer la méthode de compilation, et c'est pas possible. Comme je le disais plus haut, tout ça est intégré dans un compilateur qui prend du C en entrée, le manipule et recrache du C en sortie.

        Du coup, je m'en suis sorti en faisant un hack à la Q&D. Pour info, c'est en rapport avec http://think.ow2.org

        Merci pour les coups de main ;)
        Marc
        • [^] # Re: option -D

          Posté par  . Évalué à 2.

          Haaa, c'est un projet sponso par Orange, je comprend mieux le pourquoi de cette méthode de compilation complètement débile...
    • [^] # Re: option -D

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

      je voulais éviter l'utilisation d'une ligne de compilation spécifique à chaque instance (cf message initial...)
  • # Pour faire dans le constructif

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

    Contrairement à ce que semblent penser les blaireaux du dessus, ce que tu fait n'est pas débile du tout.

    Un exemple tout simple, pour code une liste générique en C, c'est bien pratique. Imaginons une liste dont les éléments peut-être n'importe quoi mais en gardant un typage fort, donc pas de pointeur.

    On fait un code qui fontion sur un type générique BIDULE avec un truc du genre
    typedef struct node_s node_t;
    struct node_s {
    node_t *next;
    BIDULE value;
    };

    Et ensuite, si tu as besoin d'une liste de char tu fait :
    #define BIDULE char
    #include <listegen.inc>

    Le problème c'est quand on doit manipuler plusieur liste de type différent, il faut que les struct et les fonction aient des nom différents. Pour cela il faut utiliser l'opérateur de concaténation ##.

    exemple :
    #define TYPE char
    #include <liste.inc>

    Fichier liste.inc :
    #define ajout ajout##TYPE
    void ajout(TYPE valeur) {...}

    Dans le fichier générique tu utilise le nom générique "ajout" et une fois inclut pour un type spécifique tu utilise "ajoutchar" par exemple. (En général on fait un peut plus joli mais c'est pour l'exemple)
    Et tu peut inclure le fichier aussi souvent que tu veux avec plein de type différents.

    ------------

    Donc pour revenir à ton cas, tu peut définir un identifiant unique avec un truc de la forme "bipbip##__FILE__" par exemple si tu veux une variable global qui aie un nom différent dans chaques fichiers tu fais :

    #define mavar toto##__FILE__
    int mavar;

    En interne dans le fichier tu utilise mavar comme nom, mais une fois passée au préprocesseur elle aurra un nom unique.
    • [^] # Re: Pour faire dans le constructif

      Posté par  . Évalué à 1.

      Je suis curieux de savoir comment ça résout le problème exposé :

      J'ai un fichier en C sur lequel le cpp va passer plusieurs fois pour créer plusieurs version du code. Genre gcc -E test.c > v1.c && gcc -E test.c > v2.c , etc etc
      Au final, je vais tout lier ensemble, et ça bloque à cause de définitions multiples de certains symboles


      Petit rappel :
      Je ne peux pas définir de macro en cli (en utilisant -D), les fichiers doivent utiliser la même commande exactement.


      Je suis sûr que les blaireaux seront content d'apprendre quelque chose.

      Étienne
    • [^] # Re: Pour faire dans le constructif

      Posté par  . Évalué à 1.

      Je rajouterai ceci :
      #define mavar toto##__FILE__
      int mavar;


      Ne marchera jamais car __FILE__ est une chaîne de caractères entouré comme il se doit par des ", ce qui ne risque pas de te donner un nom de variable valide. Au mieux tu te retrouvera avec
      int toto"toto.c";

      Qui risque de difficilement compiler.

      Étienne
      • [^] # Re: Pour faire dans le constructif

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

        Aaaargh, en effet j'avais oublier les guillements. Résultat, en effet ça ne marche pas. Désolé je n'ai pas pus tester avant de poster.

        Et faut pas prendre mal le "blaireau", c'était une réaction épidermique au premier fil de réponses, ou des personnes ne répondent que pour critiquer sans chercher à comprendre le sujet.
    • [^] # Re: Pour faire dans le constructif

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

      Concernant les listes, c'est effectivement utile. J'ai pris une solution à peu prêt similaire quand j'ai eu besoin de liste "générique" à la compilation (voir http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/think/exp(...) ).

      Pour l'utilisation de __FILE__, j'avais envisagé la chose aussi, le soucis étant que les différentes versions du sources commencent par un passage du cpp sur le fichier d'origine, donc __FILE__ est toujours le même.

      Ce qui est dommage, c'est de ne pas pouvoir obtenir par exemple la date d'appel du cpp dans une forme sympa (genre YYYYDDMMHHMMSS).

      Merci quand même d'avoir essayer :)

      Marc

Suivre le flux des commentaires

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