Projet multifichiers et déclaration de structure : je m'embrouille :-(

Bonsoir,

j'ai un projet autour d'un ESP32 qui commence à être conséquent et que j'ai découpé en plusieurs fichiers .cpp et .h à côté du fichier .ino

J'ai, entre autres, un fichier pour tout ce qui est mesures (mesures.cpp et mesures.h) et un fichier pour l'interface web (srvweb.cpp et srvweb.h)

Dans mesures.cpp j'ai déclaré une structure, une variable et un tableau que j'utilise surtout dans ce même fichier. Jusque là tout va bien.

struct SDATA {
  float temp;
  long  tmillis;
//  bool err;       // les 2 bool pas encore utilisés
// bool valable;
};

SDATA last_temp;        // dernière mesure
SDATA TabMesures[3600]; // toutes les mesures

Or, j'aimerai accéder à last_temp dans le fichier srvweb.cpp donc j'ai mis dans srvweb.h :

extern struct SDATA;
extern SDATA last_temp; 

mais ça ne compile pas :

srvweb.h:20:1: error: a storage class can only be specified for objects and functions
 extern struct SDATA;
 ^~~~~~
/home/c****/srvweb.h: In function 'void handleWebSocketMessage(void*, uint8_t*, size_t)':
/home/c****/srvweb.h:21:14: error: 'last_temp' has incomplete type
 extern SDATA last_temp;
              ^~~~~~~~~
/home/c****/srvweb.h:20:15: note: forward declaration of 'struct SDATA'
 extern struct SDATA;
               ^~~~~
In file included from /home/c****/JSON_essai.ino:21:
/home/c****/srvweb.h:20:1: error: a storage class can only be specified for objects and functions
 extern struct SDATA;
 ^~~~~~

évidement si je ne mets rien, pas plus :frowning:

/home/c****/srvweb.cpp: In function 'void handleWebSocketMessage(void*, uint8_t*, size_t)':
/home/c****/srvweb.cpp:20:15: error: 'last_temp' was not declared in this scope

J'ai encore pas mal de mal avec le C++ (promis je passe commande à mon libraire du meilleur bouquin pour débutant que vous me conseillerez) mais là je sèche vraiment.

Quelqu'un peut-il m'aider ?

Bonsoir

extern struct SDATA last_temp;

Ca donne quoi .?

La premiere ligne est fausse car declare une structure donc un type extern ... c est la variable qui doit etre declaree

La deuxieme est incomplete.

Enfin si je fais pas d erreur

Bonjour,

Dans le fichier mesures.h

struct SDATA {
  float temp;
  long  tmillis;
//  bool err;       // les 2 bool pas encore utilisés
// bool valable;
};

extern SDATA last_temp;        // dernière mesure
extern SDATA TabMesures[3600]; // toutes les mesures

Dans le fichier mesures.cpp

#include "mesures.h"

SDATA last_temp;        // dernière mesure
SDATA TabMesures[3600]; // toutes les mesures

Dans le fichier srvweb.cpp

#include "mesure.h"
// ... la suite

Ça compile sans erreur ! merci

Reste à comprendre la logique qui sous-tend les inclusions de fichiers et là c'est pô gagné.

Rendez-moi les uses de mon pascal de jeunesse.

un #include dit au pré-processeur "copie à cet endroit tout le contenu du fichier dont je te donne le nom avant de compiler"

On ne fait pas d'allocation de mémoire dans un .h pour des variables sinon quand on inclut le .h dans deux fichiers différents on se retrouverait avec la variable en double lors de l'édition de liens

Dans le .h on fait des déclarations ➜ on explique au compilateur ce que sont les choses à connaître.

dans le .cpp on fait les définitions ➜ on crée les variables et le compilateur alloue un espace mémoire et généralement on met aussi l'implémentation des fonctions.

Donc j'ai intérêt à nettoyer mon code et à bien dissocier les déclarations (systématiquement dans le .h (sauf celles du .ino puisqu'il n'y a pas de .h) des définitions (dans les .cpp)

C'est ça ?

Oui c'est ça.

(une définition c'est à la fois la déclaration + réservation de la mémoire / création de la variable. C'est cela que vous ne voulez faire qu'une seule fois même si vous faites un #include du .h dans 30 .cpp ou .ino différents pour votre projet)

Les variables que l'on veut faire connaître au reste du code sont donc déclarées en extern dans le .h et réellement définies dans le .cpp

toto.h

#ifndef _TOTO_H_
#define _TOTO_H_

// les déclarations 
extern int totoEntier;
extern double totoReel;

void initToto(int x, double y = 22); // pas besoin d'extern pour les fonctions. On met les valeurs par défaut dans le .h, pas le .cpp
#endif

et toto.cpp

#include "toto.h"

// les définitions
int totoEntier;
double totoReel;

// cette fonction n'étant pas dans le .h les autres fichiers ne peuvent pas l'utiliser
void fonctionCacheeNonConnueEnDehorsDeTotoCpp() {
  totoEntier++;
}

// cette fonction est connue dans le .h donc fait partie de l'API de toto
void initToto(int x, double y) {
  totoEntier = x;
  totoReel = y;
  fonctionCacheeNonConnueEnDehorsDeTotoCpp();
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.