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 :

[Séparer son code] quelques petites questions.


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut [Séparer son code] quelques petites questions.
    Bonjour,

    je suis en train de démarrer un petit projet (pas d' ide tout à la main) et je m' interroge sur la façon dont je 'dois' séparer mon code.

    Donc j' ai quelques petites questions de débutant en code séparé :

    Programmant avec GTK je suis amené a traiter une (des) fonctions de callaback.
    Mais comme je sais qu' elle sera grande, et pour le clarté de mon code, je souhaite la mettre dans un autre fichier.

    Problème : Le seul argument 'data' que peut prendre cette fonction est un pointeur void :

    -Si 'main.c' lui passe des données structurées à travers ce pointeur void, il me sera inutile dans la fonction puisque la définition de la donnée structuré est dans le fichier 'main.c'. non ?

    -Ensuite je vois partout l' utilisation d' entêtes .h faisant interface avec un corps en .c Mais je n' ai jamais réussi a en comprendre l' intérêt, si ce n' est de la clarté (quand le corps contient des 12aines de fonctions) et la possibilité de compiler son code séparément (on ne peut pas le faire en incluant seulement des .c ? ) . Donc j' aurais tendance a faire directement un .c de ma fonction et a l' inclure, quel est en serait le mal?

    -J' ai aussi compris qu' il fallait linker ses fichiers. Pourtant en faisant des test (un fichier main.c incluant une fonction présente dans un fichier fonction.c) j' ai constaté que ça marchait, dans quel cas le linkage est-il nécessaire ?

    voilà pour les questions laissant voir que je n' ai rien compris à certaines choses.
    si vous avez le temps. merci ;°)

  2. #2
    Membre habitué Avatar de Ksempac
    Inscrit en
    Février 2007
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 165
    Points : 185
    Points
    185
    Par défaut
    En théorie, tu ne devrais pas pouvoir inclure des fichiers .c (jentends par inclure utiliser l'instruction #include fonction.c et non pas faire un copier coller de toute la fonction dans main.c). Et meme si ton compilateur laisse passer ca c'est tres moche.

    Inclure le fichier fonction.h dans main.c permet au compilateur de connaitre les parametres et le type de retour de la fonction qui est dans fonction.c afin qu'il vérifie que l'appel de fonction est correct.

    Un .h peut aussi servir dans le cas de ton pointeur void. Si tu fais un .h commun nommé types.h par exemple, tu peux définir la structure dedans, et inclure le .h dans les 2 fichiers .c. A partir de la, les 2 fonctions seront capables d'utiliser ta structure. Ainsi tu pourrais envoyer un void* a la fonction du fichier fonction.c et elle pourra faire un cast de void* vers mastructure*.

    Le linker est executé apres la compilation. Il recupere le code compilé de toutes les fonctions que tu utilises (que ce soit une fonction a toi ou une fonction d'une bibliotheque que tu utilises) et les lient en un seul programme executable (A noter que dans le cas des librairies partagées Unix ou DLL Windows le code compilé n'est pas rajouté dans l'executable, seul un lien vers la bibliotheque est créé).

  3. #3
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par echantillon
    Donc j' aurais tendance a faire directement un .c de ma fonction et a l' inclure, quel est en serait le mal?
    Pour quelque chose de petit, ca passe. Pour quelque chose de plus gros... je travaille sur une application dont les sources font plus de 40000 fichiers (oui, quarante mille et ce ne sont les fichiers que j'ai a ma disposition; il y a des bibliotheques developpees dans la compagnie dont je n'ai pas les sources). Imagine le temps de compilation si tout devait etre recompile apres chaque changement.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    Bonjour, et merci pour vos réponses.
    Alors :
    "Pour quelque chose de petit, ca passe."
    La seule chose qui m' embête c' est de créer un .h pour un .c qui ne contient qu' une fonction : Si je souhaite sortir 3 ou 4 fonctions bien précise dans des fichiers différents, j' arriverais à 6 ou 8 fichiers avec les .h . C' est vraiment nécessaire pour un si petit projet ? (Mais je comprend l' intérêt quand il y a beaucoup de fichiers.)

    Concernant le compilateur :
    "Inclure le fichier fonction.h dans main.c permet au compilateur de connaitre les parametres et le type de retour de la fonction qui est dans fonction.c afin qu'il vérifie que l'appel de fonction est correct. "
    Je pensais que c' était déjà le cas ?
    Le compilateur ne fait t' il pas un vérification des arguments et de ce que renvoie la fonction, juste avec sa déclaration (pas son prototype), aussi rigoureuse qu' avec un prototype ?

    Pour la structure :Je croyais que les .h ne servaient que d' interface à des fonctions ? Comment ce passe la déclaration d' une structure dans un autre fichier (exactement de la même façon que dans un main, et c' est tout ?)?

    Voilà, c' est tout ce que je me pose comme questions pour le moment ;°)

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Salut,

    Je pense que même pour un petit projet, c'est une bonne chose que l'organisation en fichiers reflète l'architecture de l'application.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par echantillon
    je suis en train de démarrer un petit projet (pas d' ide tout à la main) et je m' interroge sur la façon dont je 'dois' séparer mon code.
    Le découpage du projet en blocs fonctionnels est le résultat de la conception. Je rappel qu'il y a du travail à faire en amont du codage (définition, conception)...
    Donc j' ai quelques petites questions de débutant en code séparé :

    Programmant avec GTK je suis amené a traiter une (des) fonctions de callaback.
    Mais comme je sais qu' elle sera grande, et pour le clarté de mon code, je souhaite la mettre dans un autre fichier.

    Problème : Le seul argument 'data' que peut prendre cette fonction est un pointeur void :

    -Si 'main.c' lui passe des données structurées à travers ce pointeur void, il me sera inutile dans la fonction puisque la définition de la donnée structuré est dans le fichier 'main.c'. non ?
    Un en-tête est fait pour précisément contenir des informations 'partagées' entre plusieurs fichiers, comme des définitions de structures.
    -Ensuite je vois partout l' utilisation d' entêtes .h faisant interface avec un corps en .c Mais je n' ai jamais réussi a en comprendre l' intérêt, si ce n' est de la clarté (quand le corps contient des 12aines de fonctions) et la possibilité de compiler son code séparément
    http://emmanuel-delahaye.developpez....ganiser_source
    http://emmanuel-delahaye.developpez.....htm#organiser

    (on ne peut pas le faire en incluant seulement des .c ? ) . Donc j' aurais tendance a faire directement un .c de ma fonction et a l' inclure, quel est en serait le mal?
    C'est techniquement possible, mais un compilateur ne peut pas avaler un fichier source d'une taille infinie (une application industrielle fait 1 à 10 millions de lignes de codes, voire plus). De plus il est possible qu'une partie du code soit réutilisable ailleurs, d'où l'intérêt de le séparer. Enfin, les parties de codes doivent être le plus autonomes possibles et pouvoir être testées séparément.

    Tout est donc fait pour favoriser la compilation séparée, qui est un des principes recherchés dans les langages de programmation.
    -J' ai aussi compris qu' il fallait linker ses fichiers. Pourtant en faisant des test (un fichier main.c incluant une fonction présente dans un fichier fonction.c) j' ai constaté que ça marchait, dans quel cas le linkage est-il nécessaire ?
    La technique de production de code est immuable :

    http://emmanuel-delahaye.developpez....htm#production

    Mais les étapes sont plus ou moins visibles.

    Donc même si tu as l'impression de ne pas appeler le linker explicitement, gcc ou ton IDE le fait pour toi.
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    merci pour les conseils et les précisions.

    Après avoir mi de l'ordre dans mon arborescence, elle ressemble maintenant à ceci:
    /includes/interface.h
    /includes/clic.h

    /mimo.c (main)
    /clic.c

    Je me suis donc mi aux makefiles pour gérer mon projet, mais je ne parviens pas à dépasser un problème: mon 'main' ne reconnait pas une fonction définie dans l' include 'clic.h'.
    Je vous poste le makefile pour que vous y voyez plus clair :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Compilateur=gcc
    Options=`pkg-config --cflags --libs libgnomeui-2.0`-I/usr/include/panel-2.0
    Warnings=-Wall
     
    Mimo: mimo.o clic.o test.o
    	$(Compilateur) mimo.o clic.o -o Mimo
     
    clic.o: clic.c include/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c clic.c -o clic.o
     
    mimo.o: mimo.c includes/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c mimo.c -o mimo.o
    Je suis sûr du reste de mon code.
    Ce que je n' ai pas bien compris, c' est comment dans le makefile, faire la relation entre le .h et son .c , et si dois déclarer les .h en tant que dépendance à chaque fois ?
    J' ai bien sûr lu des documents sur les makefiles mais les méthodes changent à chaque démonstration .
    Voilà, je crois qu' après ça j' en aurais fini pas mal de questions concernant la séparation des sources. merci encore ;°)

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par echantillon
    Après avoir mi de l'ordre dans mon arborescence, elle ressemble maintenant à ceci:
    /includes/interface.h
    /includes/clic.h

    /mimo.c (main)
    /clic.c
    OK
    Je me suis donc mi aux makefiles pour gérer mon projet, mais je ne parviens pas à dépasser un problème: mon 'main' ne reconnait pas une fonction définie dans l' include 'clic.h'.
    'Définie' ? J'espère que tu veux dire 'déclarée' (prototype).

    http://emmanuel-delahaye.developpez....tm#definitions
    Je vous poste le makefile pour que vous y voyez plus clair :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Compilateur=gcc
    Options=`pkg-config --cflags --libs libgnomeui-2.0`-I/usr/include/panel-2.0
    Warnings=-Wall
     
    Mimo: mimo.o clic.o test.o
    	$(Compilateur) mimo.o clic.o -o Mimo
     
    clic.o: clic.c include/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c clic.c -o clic.o
     
    mimo.o: mimo.c includes/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c mimo.c -o mimo.o
    J'ai un doute concernant ces caractères : `
    Je suis sûr du reste de mon code.
    Ce que je n' ai pas bien compris, c' est comment dans le makefile, faire la relation entre le .h et son .c ,
    La seule relation qu'il y a est la dépendance que tu as définie. Ensuite, c'est le compilateur (et non le make) qui suit les directives de compilations du code source, dans lequel il est ecrit #include "...h". Le contenu du .h est alors compilé comme faisant partie intégrante du .c.

    et si dois déclarer les .h en tant que dépendance à chaque fois ?
    Oui.

    http://emmanuel-delahaye.developpez.com/make.htm
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par echantillon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Compilateur=gcc
    Options=`pkg-config --cflags --libs libgnomeui-2.0`-I/usr/include/panel-2.0
    Warnings=-Wall
     
    Mimo: mimo.o clic.o test.o
    	$(Compilateur) mimo.o clic.o -o Mimo
     
    clic.o: clic.c include/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c clic.c -o clic.o
     
    mimo.o: mimo.c includes/clic.h includes/interface.h
    	$(Compilateur) $(Options) $(Warnings) -c mimo.c -o mimo.o
    Les options fournies par `pkg-config --libs libgnomeui-2.0` sont destinée à l'éditeur de liens et non pas au compilateur. Voici une petite ré-écriture de ton makefile. Voir http://gl.developpez.com/tutoriel/outil/makefile/ pour plus de détails.

    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
    Compilateur=gcc
    # On sépare les options du compilateur de celles de l'éditeur de liens
    CFLAGS = `pkg-config --cflags libgnomeui-2.0` -I/usr/include/panel-2.0
    LDFLAGS =`pkg-config --libs libgnomeui-2.0`
    # Options destinées au réglage du niveau d'avertissements du compilateur
    Warnings=-Wall
    EXEC = Mimo
    # On liste tous les fichiers sources
    SRC= mimo.c clic.c test.c
    # On génère automatiquement la liste des fichiers objet
    OBJ = $(SRC:.c=.o)
     
    all: $(EXEC)
     
    # Edition des liens
    $(EXEC): $(OBJ)
    	$(Compilateur) -o $@ $^ $(LDFLAGS)
     
    # Liste des dépendances
    clic.o: include/clic.h includes/interface.h
    mimo.o: includes/clic.h includes/interface.h
    # Règle générique pour la création d'un fichier objet à partir d'un fichier d'implanation
    %.o: %.c
    	$(Compilateur) -c -o $@ $< $(CFLAGS) $(Warnings)
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    'Définie' ? J'espère que tu veux dire 'déclarée' (prototype).
    oui, pardon !

    J'ai un doute concernant ces caractères : `
    Non, la compilation fonctionnait très bien avant que je sépare mes fichier.
    Le problème ne semble pas venir de là.

    La seule relation qu'il y a est la dépendance que tu as définie. Ensuite, c'est le compilateur (et non le make) qui suit les directives de compilations du code source, dans lequel il est ecrit #include "...h". Le conteu du .h est alors compilé comme faisant partie intégrante du .c.
    Ici je parlais de la correspondance entre le .h de l' interface d' une bibliothèque, et le .c de cette bibliothèque. C' est bien ça que vous aviez compris ?
    merci.

  11. #11
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Et en plus il manque l'"include path", c'est à dire le chemin pour que le compilateur trouve les .h (j'inclue dans le make de mujigka) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ...
    INC_DIR = ./includes
    INC_FLAG = -I$(INC_DIR)
    ...
    
    
    	$(Compilateur) -c -o $@ $< $(CFLAGS) $(Warnings) $(INC_FLAG)
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    Alors, j' ai remplacé mon makefile par celui de mujigka, puis rajouter les options de souviron34 pour préciser le chemin de mes libraires si j' ai bien compris.

    J' ai ensuite remplacer
    INC_DIR = ./includes
    Par
    INC_DIR = includes

    et finalement j' ai toujours la même erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mimo.c:56: erreur: « clic » non déclaré (première utilisation dans cette fonction)
    mimo.c:56: erreur: (Chaque identificateur non déclaré est rapporté une seule fois
    mimo.c:56: erreur: pour chaque fonction dans laquelle il apparaît.)
    make: *** [mimo.o] Erreur 1

  13. #13
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Les liens fournis précédemment l'expliquent bien, mais il semble intéressant de s'assurer que tu aies pleinement compris comment fonctionne la compilation d'un programme, et le rôle de la directive préprocesseur "#include"...

    En effet, tu dois te dire que, quand le compilateur gère une ligne (mettons la ligne n°15, pour l'exemple), il ne connait que ce qu'il a déjà rencontré avant d'y arriver (autrement dit, les 14 premières lignes, selon l'exemple) et ne se souvient en aucun cas du travail qu'il a pu effectuer pour compiler un autre fichier.

    La première étape de la compilation, c'est, de gérer les différentes directives préprocesseur:

    En gros, et de manière non exhaustive:
    • remplacer "physiquement" l'ensemble des noms définis avec la directive #define ... par leur signification réelle
    • "copier" physiquement le contenu des fichier inclus avec la directive #include à l'emplacement où se trouve la directive
    • supprimer "physiquement" les parties de compilation conditionnelles en fonction des termes existants s'il échoit (gestion des directive #ifdef/#ifndef....#endif)


    Une fois que ces modifications sont effectuées, le fichier résultant sera, comme tout bon livre, traité de haut en bas et de gauche à droite, en ne connaissant que ce qui a été apperçu les lignes précédentes

    Tu l'auras surement remarqué, il n'est pas rare, quand tu définis les différentes instructions à effectuer au sein d'une fonction, que tu fasse appel à une autre fonction que tu as définie ailleurs...

    C'est pour que le compilateur aie déjà rencontré les différentes fonctions/structures auxquelles tu peux faire appel que l'on regroupe leur déclaration dans un (ou plusieurs) fichiers d'entetes et que l'on inclut ces fichiers d'entete à l'aide de la directive préprocesseur #include

    Maintenant, pour que le préprocesseur puisse faire son travail correctement, il faut, et tu l'as bien fait, le configurer dans le makefile de manière à ce qu'il connaisse les différents dossiers dans lesquels il a une chance de trouver les fichiers d'entete... Mais cela ne suffit pas...

    Tu as en effet beau lui avoir dit qu'il trouveras les fichiers d'entete dans (par exemple) /usr/include, si tu ne lui dit pas quel fichier d'entete il doit copier... il ne sera pas plus avancé

    C'est la raison pour laquelle, si le compilateur te sort une erreur parce qu'il se trouve confronté à une "undefined reference to (nom de fonction)", c'est qu'il y a de fortes chances que tu aies oublié de préciser la directive #include du fichier d'entete dans laquelle se trouve la déclaration de la dite fonction...

    Nota: fais attention aux noms de dossiers/fichiers dans ton makefile: on trouve
    • include/clic.h et
    • includes/clic.h

    à mon avis, il n'y a qu'un seul des dossier qui est bon (include ou includes)... s'il ne trouve déjà pas le dossier dans lequel aller chercher le fichier, il y a très peu de chances qu'il trouve le fichier à inclure
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    J' apprécie beaucoup toutes vos explication, merci ;°)

    Mais .. non ça ne marche toujours pas !
    J' ai bien corrigé ma faute, re-re-vérifié que mon mimo.c inclue bien clic.h (juste en dessous de l' include interfac.h dont je me sert pour déclarer une variable avec le type définie dans cet include, et sans erreurs) et toujours la même erreur.

    edit :
    après avoir repassé mes sources de long en large je ne trouve toujours pas d' pù vient le problème .. Brrrr compliqué pour si peu !
    Du coup je poste mes sources, en espérant que ça ne dérange pas trop :

    mimo.c
    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
    //--------------------------------------------------------------------------------------------------
    // Définitions
    //--------------------------------------------------------------------------------------------------
    #include <string.h>
    #include <panel-applet.h>
    #include <gtk/gtklabel.h>
     
    #include "includes/interface.h"
    #include "includes/clic.h"
     
    //--------------------------------------------------------------------------------------------------
    // Fonction premièrement apellée lors du clic sur le menu des préférences.
    //--------------------------------------------------------------------------------------------------
    void preferences (BonoboUIComponent *uic, void *applet, const gchar *verbname) // Fonction déstiné à partir elle aussi......
    {
     
    }
     
    //--------------------------------------------------------------------------------------------------
    // Initialisation de l' applet.
    //--------------------------------------------------------------------------------------------------
    // Fonction d' initialisation.
    static gboolean initialise (PanelApplet *applet,   const gchar *iid,   gpointer data)
    {
     
    	INTERFACE interface;
     
    	if (strcmp (iid, "OAFIID:Mimo") != 0)
    		return FALSE;
     
        // Menu du bouton droit .
        static const char menu_xml [] =
            "<popup name=\"button3\">\n"
            "   <menuitem name=\"Propriétés\" "
            "             verb=\"Propriétés\" "
            "           _label=\"Préférences\"\n"
            "          pixtype=\"stock\" "
            "          pixname=\"gtk-properties\"/>\n"
            "</popup>\n";
     
        static const BonoboUIVerb menu_bonobo [] = 
        {
            BONOBO_UI_VERB ("Propriétés", preferences),
            BONOBO_UI_VERB_END
        };
     
        panel_applet_setup_menu (PANEL_APPLET (applet), menu_xml, menu_bonobo, NULL);
     
        interface.event_principal = gtk_event_box_new ();
        gtk_container_add (GTK_CONTAINER (applet), interface.event_principal);
     
        interface.label_principal = gtk_label_new ("Choisir une radio");
        gtk_container_add (GTK_CONTAINER (interface.event_principal), interface.label_principal);
     
        // Connection du signal du clic gauche.
        g_signal_connect (G_OBJECT (interface.event_principal), "button_press_event", G_CALLBACK (clic), &interface);
     
    	gtk_widget_show_all (GTK_WIDGET (applet));
    	return TRUE;
    }
     
    // Connection de la fonction d' initialisation.
    PANEL_APPLET_BONOBO_FACTORY ("OAFIID:Mimo_Factory", PANEL_TYPE_APPLET, "Mimo", "0.1", initialise, NULL);
    clic.c
    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
    #include <gtk/gtklabel.h>
     
    #include "includes/interface.h"
     
    gboolean clic (GtkWidget *event_box, GdkEventButton *event, gpointer data)
    {
        if (event->button != 1)
            return FALSE;
     
        INTERFACE *interface = data;
     
        gtk_label_set_label (GTK_LABEL (interface->label_principal), "Test label applet");
     
     
    	return TRUE;
    }
    includes/interface.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef H_INTERFACE
    #define H_INTERFACE
     
    typedef struct INTERFACE
    {
        GtkWidget *event_principal;
        GtkWidget *label_principal;
    } INTERFACE;
     
    #endif
    includes/clic.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef H_CLIC
    #define H_CLIC
     
    gboolean clic (GtkWidget *event_box, GdkEventButton *event, gpointer data);
     
    #endif
    Voilà, c' est tout.
    J' ai passé pas mal de temps à chercher l' erreur mais j' ai l' impression quelle se moque de moi.
    Si vous la voyez, merci d' avoir pris le temps .
    Si c' est le makefile qui bèche voici son contenu :
    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
    Compilateur=gcc
     
    # On sépare les options du compilateur de celles de l'éditeur de liens
    CFLAGS = `pkg-config --cflags libgnomeui-2.0` -I/usr/include/panel-2.0 -Iincludes
    LDFLAGS =`pkg-config --libs libgnomeui-2.0`
     
    # Options destinées au réglage du niveau d'avertissements du compilateur
    Warnings=-Wall
    EXEC = Mimo
     
    # On liste tous les fichiers sources
    SRC= mimo.c clic.c
     
    # On génère automatiquement la liste des fichiers objet
    OBJ = $(SRC:.c=.o)
     
    all: $(EXEC)
     
    # Edition des liens
    $(EXEC): $(OBJ)
    	$(Compilateur) -o $@ $^ $(LDFLAGS)
     
    # Liste des dépendances
    clic.o: includes/clic.h includes/interface.h
    mimo.o: includes/clic.h includes/interface.h
     
    # Règle générique pour la création d'un fichier objet à partir d'un fichier d'implantation
    %.o: %.c
    	$(Compilateur) -c -o $@ $< $(CFLAGS) $(Warnings)
    Une idée !?

    EDIT : Les sources ont été mises a jours pour les besoins de ce poste :
    http://www.developpez.net/forums/sho...4&postcount=21

  15. #15
    Membre habitué Avatar de Ksempac
    Inscrit en
    Février 2007
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 165
    Points : 185
    Points
    185
    Par défaut
    L'erreur vient de tes #ifndef

    tu ecris dans tes 2 fichiers .h le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #ifndef H_GL_HELLO
    #define H_GL_HELLO
    (...)
    #endif
    Il faut bien comprendre ce que ces 3 lignes signifient :

    SI l'etiquette H_GL_HELLO n'est pas définie (#ifndef)
    ALORS definis l'etiquette H_GL_HELLO et (#define)
    lis le fichier jusqu'au #endif (#endif)

    Du coup dans ton main le compilo rentre dans le premier .h, rentre dans le ifndef, definis l'etiquette, et lis le .h, puis il entre dans le second .h, vois que l'etiquette est deja définie, et saute tout ce qu'il ya entre le #ifndef et le #endif...c'est a dire tout ton .h

    Il faut définir une etiquette differente pour chaque .h. En general on choisit un nom faisant reference au nom du fichier suivant une convention qu'on se fixe. Par exemple, H_CLIC et H_INTERFACE. L'essentiel est de choisir une notation et de s'y tenir pour justement eviter de définir 2 fois la meme etiquette.

  16. #16
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Une bonne petite technique pour créer les protections contre les inclusions multiples: http://emmanuel-delahaye.developpez....ganiser_source dans la partie Protection contre les inclusions multiples
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  17. #17
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par echantillon
    clic.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include "includes/interface.h"
     
    static gboolean clic (GtkWidget *event_box, GdkEventButton *event, gpointer data)
    Le voilà ton bug...

    http://emmanuel-delahaye.developpez....tes.htm#static
    Pas de Wi-Fi à la maison : CPL

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 81
    Points : 39
    Points
    39
    Par défaut
    "L'erreur vient de tes #ifndef"
    ralala.. Ce n' est pas quelque chose que je n' avais pas compris en plus. Je plane hein!
    Brrrrrrr ...! J' ai du mal en ce moment moi. Désolé, vraiment.
    Je connaissais le qualificateur static mais en déplaçant ma fonction dans un autre fichier j' ai déplacé le static avec elle, sans plus de gène que ça..

    Pour une fois je rame vraiment c' est pas marrant! (peut-être un manque de sommeil (peut-être qu' il ne faut pas chercher ce genre d' excuse..!))
    Je n' avance pas d' un clou certainement parce-que je n' ai pas intégré la logique des makefiles dans ma tête.. (ça viendra comme le reste)

    J' ai donc corrigé tout ça mais le make me renvoie encore des erreurs que je pense inhérentes à son contenu.
    Pourtant le linkage vers libgnomeui-2.0 à bien été fait ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    mimo.o: In function `initialise':
    mimo.c:(.text+0x2f): référence indéfinie vers « panel_applet_get_type »
    mimo.c:(.text+0x5e): référence indéfinie vers « panel_applet_setup_menu »
    mimo.o: In function `main':
    mimo.c:(.text+0x194): référence indéfinie vers « panel_applet_get_type »
    mimo.c:(.text+0x1b4): référence indéfinie vers « panel_applet_factory_main »
    collect2: ld a retourné 1 code d'état d'exécution
    make: *** [Mimo] Erreur 1

  19. #19
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Pour essayer de compiler et voir où est le problème, j'aurais besoin de ton fichier mimo.c. Tu ne l'as pas encore posté, je crois?

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  20. #20
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    vérifie si t'as pas la même chose avec ces routines, ou si tu as bien inclus le fichier, ou si le répertoire ou il va le chercher est le bon..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Quelques petites questions pour bien fignoler mon appli
    Par Juho06 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 08/03/2007, 10h24
  2. quelques petites questions
    Par la debutante dans le forum Windows
    Réponses: 1
    Dernier message: 20/12/2006, 09h08
  3. quelques petites questions sur les windows form
    Par natasha84 dans le forum C++/CLI
    Réponses: 22
    Dernier message: 25/05/2006, 22h14
  4. Quelques petites questions sur le shell
    Par Badaboumpanpan dans le forum Linux
    Réponses: 8
    Dernier message: 01/04/2006, 00h09
  5. [Tk] Quelques petites questions
    Par Damian dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 06/02/2006, 16h34

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