Suddivisione codice

Salve,

sto facendo un programma in PlatformIO, non particolarmente complesso ma lungo: sono a circa 900 righe e quindi la gestione è complessa. Ho provato a creare 2 file cpp che includono un solo header, ma ricevo numerosi messaggi di variabili duplicate eccetera. Esiste un modo relativamente semplice per suddividere il codice in più file ssenza sovrapposizioni?Grazie per l’attenzione.

:slight_smile: Ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato.
Grazie.

@piero60: ... è la terza volta che ti viene segnalata la sezione sbagliata e continui a scrivere in Italiano dove non devi ... attenzione, la prossima volta si dovrà applicare un BAN. Grazie.

Guglielmo

Chiedo scusa, pensavo di aver scritto nella sezione italiano. Potreste spiegarmi come fare. Grazie

Si, esiste e viene usato da tutti programmatori in C++, per cui per i dettagli devi fare riferimento al manuale C++. Mentre in breve:

In un Header file:

  • non dichiarare variabili
  • puoi dichiarare variabili constexpr, queste saranno visibili in ogni file .cpp se viene incluso l’header file.
  • Per rendere visibili le variabili dichiarate dentro i file .cpp usa le dichiarazioni extern (non consigliato), oppure meglio crea le funzioni get/set. (Questo è criptico)
  • Proteggi gli header file dalla inclusione multipla con le macro #if, #define, #endif oppure usa #pragma once.

Nel link seguente c’è un poco di teoria valida sia per arduino ide che per platformIO.

Ciao.

Grazie, proverò ad applicare.

Ad populum adiuvandum ( non so se c’è la sezione Latino ).

Ho spostato tutte le definizioni di funzioni in un file xxx.h.

Ho messo tutte le variabili nel file xxx.cpp principale che include il xxx.h.

Ho creato un file yyy.cpp in cui ho incluso il file xxx.h. In questo file ho spostato alcune delle funzioni precedentemente nel file xxx.cpp; la dichiarazione di queste funzioni è nel file xxx.h, quindi non le ho dovute dichiarare extern. Ho invece dovuto dichiarare extern nel file yyy.cpp le variabili usate in questo file.

Adesso funziona.

Però

Nel mio programma uso un display 2.4” con la libreria MCUFRIEND_kbv. Ebbene, TUTTE le funzioni che utilizzano il display DEVONO stare nel file principale, cioè quello in cui è dichiarata la variabile MCUFRIEND_kbv tft, altrimenti il display si comporta in modo imprevedibile. Non ho idea se c’è un modo per evitare il problema, ma per adesso va bene così.

Grazie a Maurotec per i suggerimenti.

La dichiarazione MCUFRIEND_kbv tft puo comparire come extern in ogni file .cpp, ma ovviamente devi includere l’header file. Questa non è una soluzione elegante e robusta specie con le variabili. Una soluzione più elegante è creare un header file display.h che include MCUFRIEND_kbv , all’interno di display.h:

#include <MCUFRIEND_kbv.h>
extern MCUFRIEND_kbv tft;  // dichiara extern il simbolo tft creato come variabili
// di modulo nel file display.cpp
// opzionale
// #define TFT_OBJ TFTget()  

// extern MCUFRIEND_kbv &TFTget();

Nel file display.cpp :

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft; // il simbolo tft esiste

// opzionale 
// MCUFRIEND_kbv &TFTget() {
//    return tft; // restituisce l'oggetto tft
// }

Mentre nel file main.cpp:

#include "display.h"

void main() {
   // qui il simbolo tft dovrebbe essere risolvibile dal linker ld
}

La parte commentata come opzionale in realtà andrebbe implementata, l’obbiettivo è di rendere globale un simbolo come lo è ad esempio Serial , ma attraverso una macro.

Prova e fa sapere.

Ciao.

In effetti la mia idea iniziale era di racchiudere tutto quanto riguardava la gestione del display in un file separato lasciando il cuore del programma nel file .cpp originale; ma non ha funzionato.

Attualmente disegno dei pulsanti sullo schermo tramite una classe derivata da Adafruit_gfx_button, ma inizializzandoli tramite .init( &tft… ottengo risultati strani ( se tft lo dichiaro extern). Magari la funzione MCUFRIEND_kbv &TFTget() potrebbe risolvere il problema, anche se non ho chiarissimo come usarla.

Ciao e grazie

Non può dipendere da extern, questo comando viene risolto dal linker ld in fase finale di compilazione. Mentre se ho capito bene il problema lo hai durante l’esecuzione.

In effetti initButtonrichiede come primo argomento un puntatore a tipo Adafruit_GFX, però io non conosco le internals di `MCUFRIEND_kbv`, deduco che la classe MCUFRIEND_kbv eredita la classe Adafruit_GFX.

Senza vedere il codice di più non so dire, potresti semplificare i file mantenendo il minimo indispensabile per creare un pulsante inizializzarlo ecc, zippare il tutto così lo posso visionare.

Ciao.