[C] Commande du préprocesseur #define et fichiers headers !

Commande du préprocesseur #define et fichiers headers ! [C] - C++ - Programmation

Marsh Posté le 06-09-2002 à 21:24:28    

Bonjour,
 
Lorsque l'on programme en C, il est très souvent nécéssaire d'employer au début de notre fichier
de l'application la commande du préprocesseur #define, suivie de fichiers headers de diverses
librairies.
Par exemple #define <stdlib.h> va inclure le fichier header stdlib.h au début de notre fichier.
 
Mais ce fichier stdlib.h ne contient que la déclaration des fonctions et données, et non ces fonctions
en elles-même !
J'imagine que les corps de ces fonctions se trouvent dans un fichier du type stdlib.c
 
J'aimerai savoir comment se débrouille le fichier stdlib.h pour indiquer d'utiliser le fichier stdlib.c,
de sorte que dans l'application on n'a qu'à inclure le fichier header (et non stdlib.c) ???
 
Merci :hello:


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 06-09-2002 à 21:24:28   

Reply

Marsh Posté le 06-09-2002 à 21:44:51    

Le compilateur, il s'en fout.
C'est le linker qui par contre a besoin de trouver les symboles déclarés dans les .h


Message édité par verdoux le 06-09-2002 à 21:44:58
Reply

Marsh Posté le 06-09-2002 à 21:59:57    

si tu veux mon avis si ton compilo cherche ou dans tata.lib ou dans toto.lib lorsque tu inclues stdlib.h ben ... change de compilo  :D

Reply

Marsh Posté le 06-09-2002 à 22:24:44    

Le code des fonctions décrites est déjà compilé
les headers indiquent juste les fonctions qui existent et où les trouver ainsi que les structures des données pour que le linker puissent les lier à l'exe
(C un peu le même system que lorsqu'on fait appel à des DLL)
 
Si G rien compris faite moi signe  :D  
 :hello:


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:35:13    

[SDF]Poire a écrit a écrit :

Le code des fonctions décrites est déjà compilé
les headers indiquent juste les fonctions qui existent et où les trouver ainsi que les structures des données pour que le linker puissent les lier à l'exe
(C un peu le même system que lorsqu'on fait appel à des DLL)
 
Si G rien compris faite moi signe  :D  
 :hello:  



Salut,
 
 Oui tu as bien compris, merci.
Je développe une librairie qui contient plusieurs fichiers *.c, chacun contenant quelques fonctions.
Comment dois-je faire pour inclure ces fichiers dans une application ?
Dois-je créer un fichier header pour chaque fichier de la librairie, et si oui, que dois-je inclure dans les fichiers header ou les fichiers *.c pour les 'lier' ?
Sinon, quelle méthode me proposes-tu ?
 
Merci.


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 06-09-2002 à 22:35:38    

Oui c'est ça, les .h ne contiennent que des prototypes, qui ne servent qu'à vérifier que l'utilisation de la fonction en C n'est pas incorrecte. En fait, on peut même les omettre et faire des déclarations implicites (GROUIIIIIIIIIIIIIIIIIIIIKKKKKKK).
 
C'est au moment de l'édition des liens que le linker va chercher les fonctions correspondantes. Par défaut, il va au moins farfouiller dans la libc, mais on peut lui préciser des bibliothèques en plus, en lui donnant le chemin : /usr/lib/libtoto.a pour la version statique, /usr/lib/libtoto.so pour la version dynamique, ou tout simplement comme on fait habituellement, -ltoto.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 06-09-2002 à 22:41:24    

juju-le-barbare a écrit a écrit :

Salut,
 
 Oui tu as bien compris, merci.
Je développe une librairie qui contient plusieurs fichiers *.c, chacun contenant quelques fonctions.
Comment dois-je faire pour inclure ces fichiers dans une application ?
Dois-je créer un fichier header pour chaque fichier de la librairie, et si oui, que dois-je inclure dans les fichiers header ou les fichiers *.c pour les 'lier' ?
Sinon, quelle méthode me proposes-tu ?
 
Merci.




Ds les headers tu peux mettre directos le code de tes fonctions si tu veux (par exemple celles que tu utilises souvent)
aprés tu inclus ton header et ça marche
 
Si tu veux faire une bibliothéque C + compliqué
il fo que tu fasses ta bibliotheque (on pourra y acceder directement comme l'a dit Jar Jar)
Mais tu peux faire un header avec les types de données utilisés et les appels
 
GCC à des options pour lier les bibliothéques regarde la doc
 
désolé de ne pas pouvoir t'aider + mais tout ça n'est + trés rescent ds mon esprit
 
 :hello:


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:41:38    

juju-le-barbare a écrit a écrit :

Je développe une librairie qui contient plusieurs fichiers *.c, chacun contenant quelques fonctions.
Comment dois-je faire pour inclure ces fichiers dans une application ?
Dois-je créer un fichier header pour chaque fichier de la librairie, et si oui, que dois-je inclure dans les fichiers header ou les fichiers *.c pour les 'lier' ?
Sinon, quelle méthode me proposes-tu ?


Pour faire les .h, en gros tu reprends les déclarations de toutes tes fonctions, en rajoutant des extern là où il faut.
 
Pour inclure ça à l'édition des liens, tu as le choix :
- soit tu lies les fichiers objet comme tu le fais avec les fichiers objet de ton application,  
- soit tu fais une bibliothèque statique :
ar r libtoto.a *.o
- soit tu fais une bibliothèque dynamique, c'est le mieux car  c'est plus économe en mémoire, le linker dynamique ne charge que les fonctions utilisées ; pour ça il faut avoir compilé du position independent code (option -fPIC), puis tu fais :
gcc -o libtoto.so.3.5 -shared -Wl,-soname,libtoto.so *.o -lc
puis les liens symboliques libtoto.so => libtoto.so.3 => libtoto.3.5


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 06-09-2002 à 22:43:51    

Jar Jar a écrit a écrit :

Oui c'est ça, les .h ne contiennent que des prototypes, qui ne servent qu'à vérifier que l'utilisation de la fonction en C n'est pas incorrecte. En fait, on peut même les omettre et faire des déclarations implicites (GROUIIIIIIIIIIIIIIIIIIIIKKKKKKK).
 
C'est au moment de l'édition des liens que le linker va chercher les fonctions correspondantes. Par défaut, il va au moins farfouiller dans la libc, mais on peut lui préciser des bibliothèques en plus, en lui donnant le chemin : /usr/lib/libtoto.a pour la version statique, /usr/lib/libtoto.so pour la version dynamique, ou tout simplement comme on fait habituellement, -ltoto.



Et donc, dans la mesure où je crée ma propre librairie, que dois-je faire pour permettre de l'utiliser ?
Dois-je simplement créer les fichiers *.c et les ajouter dans les options ligne de commande de gcc en plus de main.c (autrement dit ne pas créer de fichier header) ?
 
Merci.


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 06-09-2002 à 22:44:35    

Jar Jar a écrit a écrit :

Pour faire les .h, en gros tu reprends les déclarations de toutes tes fonctions, en rajoutant des extern là où il faut.
 
Pour inclure ça à l'édition des liens, tu as le choix :
- soit tu lies les fichiers objet comme tu le fais avec les fichiers objet de ton application,  
- soit tu fais une bibliothèque statique :
ar r libtoto.a *.o
- soit tu fais une bibliothèque dynamique, c'est le mieux car  c'est plus économe en mémoire, le linker dynamique ne charge que les fonctions utilisées ; pour ça il faut avoir compilé du position independent code (option -fPIC), puis tu fais :
gcc -o libtoto.so.3.5 -shared -Wl,-soname,libtoto.so *.o -lc
puis les liens symboliques libtoto.so => libtoto.so.3 => libtoto.3.5




T'es pas obligé
le header peut contenir le code source des fonctions...
 
 :hello:


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:44:35   

Reply

Marsh Posté le 06-09-2002 à 22:46:04    

[SDF]Poire a écrit a écrit :

 
T'es pas obligé
le header peut contenir le code source des fonctions...


GROUIIIIIIIIIIIIKKKKK
 
Tiens, j'ai oublié de préciser un HAINAURME avantage de faire des bibliothèques dynamiques : tu peux trafiquer ta bibliothèque sans toucher au logiciel déjà compilé...


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 06-09-2002 à 22:46:25    

Exemple d'un header (de moi en +  :D enfin me suis aidé quand même hein...)
MP3.h:

Code :
  1. #ifndef _MP3_
  2. #define _MP3_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/stat.h>
  6. //layer.h
  7. class Layer {
  8. public:
  9. const char * mode_name(void);
  10. const char * layer_name(void);
  11. const char * version_name(void);
  12. const char * version_num(void);
  13. unsigned int bitrate(void);
  14. unsigned int sfreq(void);
  15. unsigned long length(void);
  16. int get(FILE * file);
  17. static const char * mode_names[5];
  18. static const char * layer_names[3];
  19. static const char * version_names[3];
  20. static const char * version_nums[3];
  21. static const unsigned int bitrates[3] [3] [15];
  22. static const unsigned int s_freq[3] [4];
  23. static const int MPG_MD_STEREO;
  24. static const int MPG_MD_JOINT_STEREO;
  25. static const int MPG_MD_DUAL_CHANNEL;
  26. static const int MPG_MD_MONO;
  27. static const int MPG_MD_LR_LR;
  28. static const int MPG_MD_LR_I;
  29. static const int MPG_MD_MS_LR;
  30. static const int MPG_MD_MS_I;
  31. private:
  32. int version;
  33. int lay;
  34. int error_protection;
  35. int bitrate_index;
  36. int sampling_frequency;
  37. int padding;
  38. int extension;
  39. int mode;
  40. int mode_ext;
  41. int copyright;
  42. int original;
  43. int emphasis;
  44. int stereo;
  45. unsigned long fileSize;
  46. };
  47. //layer.cpp
  48. const int Layer::MPG_MD_STEREO = 0;
  49. const int Layer::MPG_MD_JOINT_STEREO = 1;
  50. const int Layer::MPG_MD_DUAL_CHANNEL = 2;
  51. const int Layer::MPG_MD_MONO = 3;
  52. const int Layer::MPG_MD_LR_LR = 0;
  53. const int Layer::MPG_MD_LR_I = 1;
  54. const int Layer::MPG_MD_MS_LR = 2;
  55. const int Layer::MPG_MD_MS_I = 3;
  56. const char *Layer::mode_names[5] = {"stereo", "j-stereo", "dual-ch", "single-ch", "multi-ch"};
  57. const char *Layer::layer_names[3] = {"I", "II", "III"};
  58. const char *Layer::version_names[3] = {"MPEG-1", "MPEG-2 LSF", "MPEG-2.5"};
  59. const char *Layer::version_nums[3] = {"1", "2", "2.5"};
  60. const unsigned int Layer::bitrates[3] [3] [15] =
  61. {
  62. {
  63.  {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
  64.  {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
  65.  {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}
  66. },
  67. {
  68.  {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
  69.  {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
  70.  {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
  71. },
  72. {
  73.  {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
  74.  {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
  75.  {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
  76. }
  77. };
  78. const unsigned int Layer::s_freq[3] [4] =
  79. {
  80. {44100, 48000, 32000, 0},
  81. {22050, 24000, 16000, 0},
  82. {11025, 8000, 8000, 0}
  83. };
  84. const char * Layer::mode_name(void) { return (Layer::mode_names[mode]); }
  85. const char * Layer::layer_name(void) { return (Layer::layer_names[lay - 1]); }
  86. const char * Layer::version_name(void) { return (Layer::version_names[version]); }
  87. const char * Layer::version_num(void) { return (Layer::version_nums[version]); }
  88. unsigned int Layer::bitrate(void)
  89. { return (Layer::bitrates[version] [lay - 1] [bitrate_index]); }
  90. unsigned int Layer::sfreq(void)
  91. { return (Layer::s_freq[version] [sampling_frequency]); }
  92. unsigned long Layer::length(void) { return bitrate() ? fileSize / (unsigned long) (bitrate() / 8) : 0; }
  93. int Layer::get(FILE * file)
  94. {
  95. unsigned char *buff = new unsigned char[1024];
  96. unsigned char *buffer;
  97. size_t temp;
  98. size_t readsize;
  99. struct stat buf;
  100. fstat(fileno(file), &buf);
  101. fileSize = (unsigned long)buf.st_size;
  102. fseek(file, 0, SEEK_SET);
  103. readsize = fread(buff, 1, 1024, file);
  104. readsize -= 4;
  105. cout << "\nsize : " << readsize;
  106. cout << "\nbuff : " << buff;
  107. if (readsize <= 0) {
  108.  delete[] buff;
  109.  return 0;
  110. }
  111. buffer = buff - 1;
  112. cout << "\nbuffer : " << buffer;
  113. getch();
  114. do {
  115.  buffer++;
  116.  cout << "\nbuffer : " << buffer;
  117.  getch();
  118.  temp = ((buffer[0] << 4) & 0xFF0) | ((buffer[1] >> 4) & 0xE);
  119. } while ((temp != 0xFFE) && ((size_t) (buffer - buff) < readsize));
  120. if (temp != 0xFFE) {
  121.  delete[] buff;
  122.  return 0;
  123. } else {
  124.  switch ((buffer[1] >> 3 & 0x3)) {
  125.  case 3:
  126.   version = 0;
  127.   break;
  128.  case 2:
  129.   version = 1;
  130.   break;
  131.  case 0:
  132.   version = 2;
  133.   break;
  134.  default:
  135.   delete[] buff;
  136.   return 0;
  137.  }
  138.  lay = 4 - ((buffer[1] >> 1) & 0x3);
  139.  error_protection = !(buffer[1] & 0x1);
  140.  bitrate_index = (buffer[2] >> 4) & 0x0F;
  141.  sampling_frequency = (buffer[2] >> 2) & 0x3;
  142.  padding = (buffer[2] >> 1) & 0x01;
  143.  extension = buffer[2]  & 0x1;
  144.  mode = (buffer[3] >> 6) & 0x3;
  145.  mode_ext = (buffer[3] >> 4) & 0x03;
  146.  copyright = (buffer[3] >> 3) & 0x01;
  147.  original = (buffer[3] >> 2) & 0x1;
  148.  emphasis = (buffer[3]) & 0x3;
  149.  stereo = (mode == Layer::MPG_MD_MONO) ? 1 : 2;
  150.  delete[] buff;
  151.  return 1;
  152. }
  153. }
  154. #endif


Message édité par [SDF]Poire le 06-09-2002 à 22:48:09

---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:48:49    

Jar Jar a écrit a écrit :

GROUIIIIIIIIIIIIKKKKK
 
Tiens, j'ai oublié de préciser un HAINAURME avantage de faire des bibliothèques dynamiques : tu peux trafiquer ta bibliothèque sans toucher au logiciel déjà compilé...




ça dépend de ce qu'il veut faire aussi


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:49:19    

juju-le-barbare a écrit a écrit :

Et donc, dans la mesure où je crée ma propre librairie, que dois-je faire pour permettre de l'utiliser ?
Dois-je simplement créer les fichiers *.c et les ajouter dans les options ligne de commande de gcc en plus de main.c (autrement dit ne pas créer de fichier header) ?


Dans tous les cas, il faut créer un fichier header qui contient les prototypes des fonctions que tu veux exporter.
Exemple con :

Code :
  1. toto.c:
  2. int toto(char *coincoin, int gouzou)
  3. {
  4. blah blah
  5. ...
  6. }
  7. static char *foobar(int plop, double grouik)
  8. {
  9. bluh
  10. ...
  11. }


Ça donne :

Code :
  1. toto.h:
  2. #ifndef _TOTO_H
  3. #define _TOTO_H
  4. extern int toto(char *coincoin, int gouzou);
  5. #endif /* _TOTO_H */


 
 
Et c'est tout, pas de code pour toto, et pas de prototype pour foobar qui est statique.
 
Ensuite, tu as le choix entre les 3 méthodes que je t'ai données. Pour une petite lib, tu peux te contenter de compiler les fichiers ensemble, mais pour une grosse la bibliothèque dynamique finit par devenir indispensable.
 
Edit: j'avais oublié les _TOTO_H.


Message édité par Jar Jar le 06-09-2002 à 22:50:30

---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 06-09-2002 à 22:50:54    

Jar Jar a écrit a écrit :

Dans tous les cas, il faut créer un fichier header qui contient les prototypes des fonctions que tu veux exporter.
Exemple con :
 
[..]
 
Ensuite, tu as le choix entre les 3 méthodes que je t'ai données. Pour une petite lib, tu peux te contenter de compiler les fichiers ensemble, mais pour une grosse la bibliothèque dynamique finit par devenir indispensable.




J'aimerais bien savoir ce qu'il y a ds la bibliothéque...
C ptet bien se compliquer la vie pour pas grand chose...


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 06-09-2002 à 22:57:00    

[SDF]Poire a écrit a écrit :

 
J'aimerais bien savoir ce qu'il y a ds la bibliothéque...
C ptet bien se compliquer la vie pour pas grand chose...



C'est une assez grosse bibliothèque (85 Ko de code sur plein de fichiers, et c'est loin d'être fini), je vais donc étudier toutes vos suggestions et je vous tiens au courant.
 
Merci à vous :hello:


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 06-09-2002 à 22:58:19    

juju-le-barbare a écrit a écrit :

C'est une assez grosse bibliothèque (85 Ko de code sur plein de fichiers, et c'est loin d'être fini), je vais donc étudier toutes vos suggestions et je vous tiens au courant.
 
Merci à vous :hello:




ds ce cas là ça peut être intéressent
 
 :hello:


---------------
Des bons sites pour Delphi? http://forum.hardware.fr/forum2.php3?post=16838&cat=10 -- informaticien -- http://www.z0rglub.com/phpwebgallery/ -- Delphi :love:
Reply

Marsh Posté le 07-09-2002 à 00:02:22    

juju-le-barbare a écrit a écrit :

Et donc, dans la mesure où je crée ma propre librairie, que dois-je faire pour permettre de l'utiliser ?
Dois-je simplement créer les fichiers *.c et les ajouter dans les options ligne de commande de gcc en plus de main.c (autrement dit ne pas créer de fichier header) ?
 
Merci.




 
pour faire ca proprement, tu dois:
 
 - creer un fichier header pour chaque fichier.c ( ou regrouper par fonctions)
 - include le header dans chaque .c utilisant les fonctions d'un autre
 
lors de la compilation, tu transformes tout en code objet:
 
gcc -c fichier.c -o fichier.o
 
et le linkage (rassemblement de tout ca):
gcc machin.o truc.o , etc...
 
pour une bibliotheque c'est pareil a part que tu compiles les fichiers.c avec l'option -fPIC et que tu ajoutes -shared a l'edition des liens

Reply

Marsh Posté le 07-09-2002 à 02:23:22    

juju-le-barbare  
Le header n'indique absolument pas où se trouve le code, juste la forme de l'appel.
La plupart des environnements de développements ont une notion de projet, qui spécifie dans quels fichiers sont cherchés les codes des fonctions.
 
 

[SDF]Poire a écrit a écrit :

le header peut contenir le code source des fonctions...


Si tu fais cette GROUIIIIIIIIIIIIKKKKKerie, saches que chaque source qui inclus ce header compilera sa propre version locale de cette fonction (duplication de code), et qu'il faut donc la déclarer static.
 
 
Jar Jar
toto.c devrait inclure toto.h, ça permet de vérifier la cohérence.
 
Légers inconvénient d'une DLL:
-petit surcoût dû à l'indirection.
-empêche l'inlining.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 07-09-2002 à 02:31:31    

Musaran a écrit a écrit :

Légers inconvénient d'une DLL:
-petit surcoût dû à l'indirection.
-empêche l'inlining.


Le surcoût du à l'indirection est seulement présent sur l'architecture ia32. Avec tous les autres processeurs, ça n'engendre pas de pertes de performances.
Sinon, il me semble que libtool bidouille pour supprimer ce surcoût, mais ce n'est pas sa raison première.
 
Pour l'inlining, ça n'empêche pas d'inliner les fonctions statiques à la bibliothèque, si ?


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 07-09-2002 à 08:23:17    

<i>le header peut contenir le code source des fonctions...</i>
 

Jar Jar a écrit a écrit :

GROUIIIIIIIIIIIIKKKKK




 
gcc && C++ && utilisation de templates :+)


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 07-09-2002 à 10:00:06    

Merci,
 
Petite précision que j'avais omi, je suis sous environnement Unix (GNU/Linux pour être précis), mais vous l'aviez deviné (comment, je le sais pas...).
 
Bref désolé de vous paraître lourd, mais c'est la première fois que je créé une librairie :)
 
Donc je créé un fichier fonctions1.c qui contient par exemple 10 fonctions, puis 1 fichier fonctions1.h qui contient la déclaration de ces fonctions.
Mais pour indiquer que fonctions1.h doit être "lié" à fonctions1.c, dois-je faire un #include "fonctions1.h" au début du fichier fonctions1.c ?
 
De même tous les fichiers fonctionsn.c nécéssitent tous le même et unique fichier base.c (et son header base.h), je dois donc inclure base.h dans chaque fonctionsn.c c'est ça ?
 
J'espère avoir été clair, et je vous remercie tous autant que vous êtes pour m'avoir aidé  :p


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 07-09-2002 à 11:25:02    

Bonjour,
 
J'ai à peu près trouvé, voici comment j'ai fait :
 
Dans chaque fonctionn.c j'ai inclus fonctionsn.h
et dans chaque fonctionsn.h, j'ai inclus base.c
(je ne peux pas inclure base.c dans fonctionsn.c, j'ai des erreurs)
 
En effet, chaque fichier fonctionsn.h dépend de base.h
 
Dans base.c j'ai inclus base.h
Et dans base.h je n'ai inclus que les headers standards (stdio.h, ...).
 
Le petit problème qui apparaît lorsque je tape :
gcc -fPIC -c fonctions1.c -o fonctions1.o
 
c'est que le fichier fonctions1.c nécéssite des fonctions de fonctions2.c.
Mais si j'inclus fonctions2.h ou fonctions2.c dans fonctions1.h ou dans fonctions1.c
(autrement dit les 4 possibilités), gcc m'indique des problèmes de redéfinitions.
 
Ne pas oublier que fonctions2.h inclus aussi base.h !
 
Donc dois-je utiliser des commandes du préprocesseur pour éviter celà ?
Si oui, que dois-je taper exactement ?
 
Merci !


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 07-09-2002 à 13:09:38    

1 - on n'inclut pas le .c dans le .h  
2 - on protege ses headers contres les inclusions recursives:

Code :
  1. #ifndef MONHEADER_H
  2. #define MONHEADER_H
  3. //.. ici mes declarations de fonctions
  4. #endif MONHEADER_h


3 - on spécifie static toutes les fonctions qui sont spécifiques à un module. (toutes celles dont le prototype n'est pas dans le header)
4 - plutot que de se taper les gcc -?? à la main on se fait un makefile ou on utilise des outils plus évolués (un ide?).
 
LeGreg

Reply

Marsh Posté le 07-09-2002 à 14:38:54    

juju-le-barbare a écrit a écrit :

 
Par exemple #define <stdlib.h> va inclure le fichier header stdlib.h au début de notre fichier.




 
Il est bizzare ton compilo! ;)

Reply

Marsh Posté le 07-09-2002 à 15:09:58    

Ace17 a écrit a écrit :

 
 
Il est bizzare ton compilo! ;)



Oups, merde, me suis trompé : c'est '#include' que je voulais dire ...


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 07-09-2002 à 15:16:16    

legreg a écrit a écrit :

1 - on n'inclut pas le .c dans le .h  
2 - on protege ses headers contres les inclusions recursives:

Code :
  1. #ifndef MONHEADER_H
  2. #define MONHEADER_H
  3. //.. ici mes declarations de fonctions
  4. #endif MONHEADER_h


3 - on spécifie static toutes les fonctions qui sont spécifiques à un module. (toutes celles dont le prototype n'est pas dans le header)
4 - plutot que de se taper les gcc -?? à la main on se fait un makefile ou on utilise des outils plus évolués (un ide?).
 
LeGreg



Donc, dans chaque fichier 'fonctionsn.h', je dois taper
#ifndef MONHEADER_H
#define MONHEADER_H
// ... ici mes declarations de fonctions
#endif MONHEADER_H
Mais à quoi correspond 'MONHEADER_H', et dans '... ici mes declarations de fonctions', que dois-je mettre : un '#include "base.h"' ?
Sinon, que dois-je mettre ?
Mieux : où pourrais-je trouver de la doc sur les commandes du préprocesseur ?
 
Merci !


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 07-09-2002 à 16:11:58    

juju-le-barbare a écrit a écrit :

Mieux : où pourrais-je trouver de la doc sur les commandes du préprocesseur ?


info gcc
 
Sinon, pour tes problèmes de fichiers .h, c'est comme quand tu fais un soft... À chaque fichiers fonctionsN.c tu associe un fonctionsN.h (mais ça tu dois avoir compris), et dans ledit fichier, tu fais :
#ifndef _FONCTIONSN_H /* en changeant le N à chaque fois ! */
#define _FONCTIONSN_H
...
#endif /* _FONCTIONSN_H */
 
Ensuite, tu peux te faire un toto.h, qui contient :
#ifndef _TOTO_H
#define _TOTO_H
#include <toto/fonctions1.h>
#include <toto/fonctions2.h>
...
#endif /* _TOTO_H */
 
Bien entendu, n'oublie pas de mettre tes h dans un sous répertoire include/toto, et de faire un -I${srcdir}/include dans tes compilations.
Ensuite, tu inclus ton toto.h, d'une part dans tous les fichiers .c de la bibliothèque, d'autre part dans tous les programmes qui utilisent ladite bibliothèque.
 
Si tu as vraiment du mal, n'hésite pas à regarder le code des Makefile d'une bibliothèque simple, tu comprendras plus vite avec UTSL qu'avec des heures d'explications.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 07-09-2002 à 20:53:56    

Juju, dans ton post initial, tu as mis #define au lieu de #include.
 
Moi aussi je recommande la syntaxe
 
#ifndef MON_FICHIER_H_A_INCLURE
#define MON_FICHIER_H_A_INCLURE
..............
#endif /* MON_FICHIER_H_A_INCLURE */
 
J'ai encontré ce genre de pratique systematique pour la premiere fois dans l'implementation de XWindows il y a une quinzaine d'années.
 
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 07-09-2002 à 21:06:33    

juju-le-barbare a écrit a écrit :

Bonjour,
 
J'ai à peu près trouvé, voici comment j'ai fait :
 
Dans chaque fonctionn.c j'ai inclus fonctionsn.h
et dans chaque fonctionsn.h, j'ai inclus base.c
(je ne peux pas inclure base.c dans fonctionsn.c, j'ai des erreurs)
 
En effet, chaque fichier fonctionsn.h dépend de base.h
 
Dans base.c j'ai inclus base.h
Et dans base.h je n'ai inclus que les headers standards (stdio.h, ...).
 
Le petit problème qui apparaît lorsque je tape :
gcc -fPIC -c fonctions1.c -o fonctions1.o
 
c'est que le fichier fonctions1.c nécéssite des fonctions de fonctions2.c.
Mais si j'inclus fonctions2.h ou fonctions2.c dans fonctions1.h ou dans fonctions1.c
(autrement dit les 4 possibilités), gcc m'indique des problèmes de redéfinitions.
 
Ne pas oublier que fonctions2.h inclus aussi base.h !
 
Donc dois-je utiliser des commandes du préprocesseur pour éviter celà ?
Si oui, que dois-je taper exactement ?
 
Merci !



D'autre part, juju, tu ne devrais pas avoir a inclure un .c dans un .h. Il y a certainement un pb dans la structuration de ton programme,
Tu devrais avoir uniquement a inclure base.h comme ceci:
 
dans fonction1.c :
/* headers des librairies standard utilisées */
#include "base.h"  /* perso, je preferre des includes explicites avec #include <stdio.h>,... partout */
/* headers des fonctions et datatypes externes */
#include "fonction2.h"
.....................
/* headers des fonctions et datatypes locales */
#include "fonction1.h"  /* devrait etre ton dernier #include */
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2002 à 00:56:10    

Merci,
 
Je tiens précieusemnt compte de vos remarques, merci encore.
Je vous tient au courant en cas d'échec (on sait jamais :p )
 
@++


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 08-09-2002 à 04:00:52    

legreg, Jar Jar, gilou et tous les autres

Code :
  1. fichier machin.h
  2. #ifndef MACHIN_H
  3. #define MACHIN_H
  4. //..declarations-définitions ne générant pas de code.
  5. #endif MACHIN_H


 
J'aimerais savoir s'il y a moyen d'automatiser cette formule, de générer automatiquement un identifiant, pour ne pas avoir besoin de choisir de nom.
Je pensais à la macro __FILE__, mais:
1) Elle donne une chaîne, et il n'y a pas d'opérateur de dé-chaînage.
2) Les caractères accentués et les sigles (dont le point du ".h" ) donneraient une erreur de compilation.
3) Les espaces tronqueraient le nom: risque d'homonymie.
 
Des idées ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 08-09-2002 à 04:03:22    

juju-le-barbare a écrit a écrit :

Mais pour indiquer que fonctions1.h doit être "lié" à fonctions1.c, dois-je faire un #include "fonctions1.h" au début du fichier fonctions1.c ?


C'est dans l'autre sens:
'fonctions1.c' fait '#include "fonctions1.h"' pour utiliser ce qu'il y a dedans.
La relation inverse n'existe pas dans le langage, c'est le système de compilation qui doit trouver les bonnes fonctions dans les sources qu'on lui indique.
 
Les headers ne doivent contenir que des trucs ne générant pas de code:

Code :
  1. //C(++)
  2. #define
  3. #include .h
  4. typedef
  5. enum
  6. struct
  7. //C++ seulement
  8. const
  9. class
  10. inline
  11. template


Sinon quoi ?
Eh bien chaque source l'incluant compilera un exemplaire du truc pour lui-même, et l'éditeur de liens ne saura pas quelle version choisir, car il ne doit y en avoir qu'une !
 
Ce système est vieux et pourri, mais il faut faire avec.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 08-09-2002 à 04:04:45    

kadreg a écrit a écrit :

gcc && C++ && utilisation de templates :+)


C'est plus une fonction, mais un patron de fonctions.
C'est très différent.
Un patron n'étant pas directement compilé, il a sa place dans le header.
On obtient le même effet (en moins bien) avec inline.
 
Le C++ est merveilleux de complexité, non ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 08-09-2002 à 04:21:33    

Jar Jar a écrit a écrit :

Le surcoût du à l'indirection est seulement présent sur l'architecture ia32. Avec tous les autres processeurs, ça n'engendre pas de pertes de performances.


Indirection: passer par un élément intermédiaire.
Typiquement un pointeur: Le lire, chercher l'élément à l'adresse indiquée.
Ce pointeur étant variable (dynamisme), il faut bien le lire, le processeur peut juste offrir un moyen rapide de le faire.
 
Une DLL étant dynamique (...), elle passe au moins par une telle indirection.
Le mécanisme virtuel du C++ utilises une telle indirection.
 
Mais bon... le surcoût équivaut à la lecture d'un pointeur, c'est très minime.
 
 

Citation :

Sinon, il me semble que libtool bidouille pour supprimer ce surcoût, mais ce n'est pas sa raison première.

je ne vois que la liaison statique pour ça...
 
 

Citation :

Pour l'inlining, ça n'empêche pas d'inliner les fonctions statiques à la bibliothèque, si ?

Effectivement pas.
Seul l'appel dynamique n'est pas compatible avec l'inlining (notion statique).


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 08-09-2002 à 07:22:01    

Musaran a écrit a écrit :

legreg, Jar Jar, gilou et tous les autres

Code :
  1. fichier machin.h
  2. #ifndef MACHIN_H
  3. #define MACHIN_H
  4. //..declarations-définitions ne générant pas de code.
  5. #endif MACHIN_H


 
J'aimerais savoir s'il y a moyen d'automatiser cette formule, de générer automatiquement un identifiant, pour ne pas avoir besoin de choisir de nom.
Je pensais à la macro __FILE__, mais:
1) Elle donne une chaîne, et il n'y a pas d'opérateur de dé-chaînage.
2) Les caractères accentués et les sigles (dont le point du ".h" ) donneraient une erreur de compilation.
3) Les espaces tronqueraient le nom: risque d'homonymie.
 
Des idées ?




Tu cherches un utilitaire nommé proto (le source c traine sur le web, GNU?) et tu le customizes.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2002 à 10:45:57    

Musaran a écrit a écrit :

Indirection: passer par un élément intermédiaire.
Typiquement un pointeur: Le lire, chercher l'élément à l'adresse indiquée.
Ce pointeur étant variable (dynamisme), il faut bien le lire, le processeur peut juste offrir un moyen rapide de le faire.


Tu veux parler du fait qu'il va chercher la fonction dans la table des symboles à chaque appel ?
Effectivement, je croyais que l'éditeur de liens dynamiques se démerdait pour ne pas requérir une telle indirection, mais à la réflexion je ne vois pas trop comment ce serait faisable...
 
Pour ma part, je pensais au fait qu'ia32 ne gère pas tout seul le code indépendant de la position, et qu'il y a donc un surcoût à chaque appel de fonction à l'intérieur de la bibliothèque, car il faut calculer l'endroit où sauter à chaque fois. Ça n'est effectivement pas une indirection, mais c'est quand même un surcoût à ne pas oublier.
 

Musaran a écrit a écrit :

Citation :

Sinon, il me semble que libtool bidouille pour supprimer ce surcoût, mais ce n'est pas sa raison première.

je ne vois que la liaison statique pour ça...


libtool est un mic-mac immonde, je n'ai jamais bien compris comment ça marche, mais il me semble qu'au final on se ramène à quelque chose qui ressemble à un binaire statique. Il est conçu au départ pour que les systèmes qui ne connaissent pas les bibliothèques dynamiques puissent en bénéficier quand même.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 08-09-2002 à 12:45:20    

Salut,
 
Je vous promet que j'ai fait omme vous m'avez dit, mais ça ne marche pas !
J'ai du oublier un tout petit élément...
 
Je ne sais pas où trouver de librairie à compiler avec un Makefile.
 
De plus j'ai quelques questions :
 
si je fais un
#define _FONCTION1_H
 
A quoi correspond exactement le _FONCTION1_H ?
 
Sinon je vais vous montrer ce que j'ai fait, corrigez-moi (je sais j'abuse :( ) :
 

Code :
  1. base.c :
  2. #include "base.h"
  3. /*Code du programme*/


 

Code :
  1. base.h :
  2. /*Déclarations des fonctions de base.c*/


 

Code :
  1. fille1.c :
  2. #include "base.h"
  3. #include "fille1.h"


 

Code :
  1. fille1.h :
  2. #ifndef _fille1_h
  3. #define
  4. /*Déclarations des fonctions de fille1.c*/
  5. #endif


 
Et toutes les autres filles de la même manière.
 
J'ai mis les fichiers base.c, base.h, filles.c , filles.h, dans le dossier /home/coder/libr/include/
Et dans le dossier /home/coder/libr/ j'ai créé un fichier libr.h qui contient :
 

Code :
  1. libr.h :
  2. #ifndef _libr_h
  3. #define
  4. #include "include/fille1.h"
  5. #include "include/fille2.h"
  6. #include "include/fille3.h"
  7. etc...
  8. #endif


 
 
Mais donc que dois-je faire pour compiler ma librairie dynamique ?
Dois-je compiler chaque .c du dossier include ?
De même quelle est l'utilité des .h, ne pourrai-je pas tout mettre dans les .c, sans déclaration ?
 
Merci
 
@++


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 08-09-2002 à 13:15:33    

Musaran a écrit a écrit :

[g]
J'aimerais savoir s'il y a moyen d'automatiser cette formule, de générer automatiquement un identifiant, pour ne pas avoir besoin de choisir de nom.




 
sous visual, par exemple, quand tu lui demandes de creer une classe il t'invente un identifiant unique a partir du nom
de fichier et te place les ifndef lui meme.
Une forme pas beaucoup plus portable c'est
de spécifier "#pragma once" dans le header
ce qui indique au preprocesseur qu'il ne faudra l'inclure
qu'une seule fois par unité ce qui permet au moins pour les projets visual de ne pas taper les "#ifndef..."
Mais je suppose que tu savais deja tout ca ??
 

Citation :

si je fais un  
#define _FONCTION1_H  
A quoi correspond exactement le _FONCTION1_H ?


 
Il ne correspond a rien. C'est le seul endroit ou il est utilisé et ne fait reference a rien de particulier.
On choisit le nom en fonction du fichier d'inclusion (fonction.h -> FONCTION_H_RANDOMID)
tout simplement pour qu'il ne puisse pas y avoir de cas de collisions entre deux identifiants identiques pour deux fichiers differents parfois on rajoute un RANDOMID pour limiter encore plus les cas de collisions (genere par macro ou par l'ide).
 

Code :
  1. #ifndef _fille1_h
  2. #define
  3. /*Déclarations des fonctions de fille1.c*/
  4. #endif


 
Mais tu defines quoi??
 
LeGreg

Reply

Marsh Posté le 08-09-2002 à 13:26:39    

legreg a écrit a écrit :

 

Code :
  1. #ifndef _fille1_h
  2. #define
  3. /*Déclarations des fonctions de fille1.c*/
  4. #endif


 
Mais tu defines quoi??




 
Et bien je définit les prototypes des fonctions qui se trouvent dans fille1.c
C'est bien ça qu'il faut faire non ?


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed