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

Arduino Discussion :

Visibilité Header et cpp [Arduino ESP32]


Sujet :

Arduino

  1. #1
    Membre averti
    Homme Profil pro
    Retraité passionné
    Inscrit en
    Mai 2021
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité passionné
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2021
    Messages : 9
    Par défaut Visibilité Header et cpp
    Bonjour, Décidément je n'arrive pas à comprendre la portée des variables entre le fichier main Header et CPP Merci de votre patience !

    J'ai une erreur à la compilation "multiples définitions".
    Je pense que je ne peux pas utiliser rxdata dans un fichier .cpp autre que dans Test1.cpp J'ai tout essayer y compris extern
    Y a-t-il une solution merci

    Fichier .ino
    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
     
    #include <Arduino.h>
    #include "Test1.h"
    #include "Test2.h"
     
    void setup()
    {
      Serial.begin(115200);
      InitData();
      loadData();
    }
     
    void loop()
    {
    }
    Fichier Test1.h
    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
     
    #ifndef TEST1_H
    #define TEST1_H
     
    #include <Arduino.h>
     
     typedef struct 
    {
      bool val1;
      bool val2;
      uint32_t ch[16];
    }Data;
     
    Data rxData;
     
    void InitData();
     
     
    #endif
    Fichier Test2.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #ifndef TEST2_H
    #define TEST2_H
     
    #include <Arduino.h>
     
    void loadData();
     
    #endif
    Fichier Test1.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include "Test1.h"
     
    void InitData(void)
    {
            rxData.ch[1] = 1;
    }
    Fichier Test2.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include "Test2.h"
    #include "Test1.h"
     
    void loadData(void)
    {
            rxData.ch[1] = 0;
    }

  2. #2
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 783
    Par défaut
    Hello,

    Dans test1.h tu déclares rxData, mais test1.h est inclus dans test1.cpp ET dans test2.cpp. D'où le message "multiple definitions".

    Une solution (non testée): déclarer dans le .ino Data rxData;, et dans test1.h et test2.h extern Data rxData; Et pour être propre, déplacer la définition de la structure Data dans un main.h, qui sera inclus dans le .ino, test1.cpp et test2.cpp

  3. #3
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 899
    Par défaut
    Il faut bien comprendre qu'en C++, une variable ou une fonction (entre autres) possède deux notions distinctes : sa déclaration et sa définition.

    La déclaration n'alloue pas de mémoire. Elle sert uniquement à indiquer au compilateur le nom utilisé et le type correspondant. Pour une fonction, on utilise son prototype, et pour une variable, le mot-clé `extern`.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void maFonction(int, int);   // Une fonction ne retournant rien et prenant deux int en paramètre
    extern unsigned long chrono; // Une variable de type unsigned long
    La définition alloue la mémoire. C'est à ce moment que le compilateur assigne une adresse à l'élément et, éventuellement, lui attribue une valeur initiale.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void maFonction(int a, int b) {
      Serial.println(a);
      Serial.println(b);
    }
     
    unsigned long chrono = 42;
    Une définition est donc une déclaration accompagnée de l'allocation mémoire et, si nécessaire, d'une valeur initiale.

    Il faut également comprendre la notion de compilation séparée : chaque fichier source est compilé indépendamment des autres. Le compilateur inject "mot pour mot" les fichiers correspondant aux directives #include et le compilateur doit connaître le nom et le type de chaque élément rencontré dans un fichier avant son utilisation. Cela signifie que toutes les fonctions et variables doivent être déclarées ou définies avant d’être utilisées.

    Une fois tous les modules compilés, la phase d'édition de lien assemble les objets. À ce stade, toutes les références aux fonctions ou variables simplement déclarées sont remplacées par leur adresse, et le binaire final est généré.

    Si le compilateur rencontre deux définitions d'une même variable globale lors de l'édition de lien, il ne peut pas choisir laquelle utiliser pour le binaire final, et la compilation échoue. C'est un bug.

    C'est la règle standard en C++. Toutefois, l'IDE Arduino ajoute une subtilité : il introduit la notion de fichier `.ino`. Si plusieurs fichiers `.ino` existent dans un sketch, l'IDE les fusionne dans un fichier temporaire unique avant la compilation, en respectant l'ordre alphabétique. Il génère ensuite un prototype pour chaque fonction trouvée dans ce fichier et l'insère en début de code, ce qui permet aux débutants d'utiliser une fonction avant sa définition.

    Si vous avez compris cela, vous avez les bases pour éviter ce type de problème.

    En pratique, le plus simple est de ne JAMAIS mettre une définition dans un fichier `.h`, uniquement des déclarations.
    Ainsi, si ce `.h` est inclus dans plusieurs fichiers `.cpp`, il n’y aura jamais de double définition. La définition doit toujours être placée dans un fichier `.cpp` ou `.ino`, et une seule fois. Cela permet de garantir que les définitions sont uniques, évitant ainsi les erreurs de double déclaration lors de la phase d'édition de lien.

  4. #4
    Membre averti
    Homme Profil pro
    Retraité passionné
    Inscrit en
    Mai 2021
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité passionné
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2021
    Messages : 9
    Par défaut Merci
    Waouh.. ça c'est clair ! je note cela précieusement. Merci beaucoup

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 27/07/2020, 01h03
  2. Fonction singleton déclarer dans header et définie dans le cpp
    Par david lefaivre dans le forum Langage
    Réponses: 3
    Dernier message: 20/02/2012, 02h19
  3. Réponses: 9
    Dernier message: 03/09/2009, 20h25
  4. classe template separe en fichier header et cpp
    Par S_ami dans le forum Langage
    Réponses: 6
    Dernier message: 03/06/2009, 11h30
  5. Réponses: 10
    Dernier message: 26/03/2009, 10h15

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