Classi multiple nella stessa libreria

Buongiorno a tutti,
sto cercando di "estendere" una libreria, aggiungendo una classe separata con la quale analizzare i dati prodotti dalla prima.

Sostanzialmente, nella libreria originale, ci sono svariati "struct" in un file header, che è poi incluso nella libreria.

Tra i vari struct c'è uno struct "Telemetry", composto a sua volta da altri struct, sempre presenti nello stesso file.

Ora, nella seconda classe, che ha i suoi file .h e .cpp, vorrei poter utilizzare come input un oggetto Telemetry, dovrei quindi includere gli stessi struct di cui sopra, me se includo nuovamente l'header sopracitato, ottengo svariati errori in quanto sia i define che gli struct sono già definiti.

Se invece lo ometto, ovviamente ho errori perché non sono definiti.

Sostanzialmente nel mio sketch ho qualcosa tipo

#include <LibA.h>
#include <LibB.h>

LibA a;
LibB b;

da quanto capisco, sia LibA.h che LibB.h dovrebbero includere ad esempio header.h

Dove sto sbagliando?

Devi fare in modo che il file dove hai definito le struct viene incluso una volta sola dal compilatore.

Per ottenere ciò il metodo più comune è quello di usare un #define


#ifndef DATA_STRUCTURES
#define DATA_STRUCTURES
.... Definizione delle tue struct

#endif

La prima volta che il compilatore incontra #include "tuofile.h", DATA_STRUCTURES non è stata ancora definita e quindi il codice viene incluso per intero.
Le volte successive invece DATA_STRUCTURES risulta già definita e quindi il blocco di codice non viene incluso.

È buona norma fare la stessa cosa per tutti i file .h
Di solito si usa qualcosa che somiglia al nome stesso del file.

Grazie mille. Avevo già provato questo metodo, senza successo.
In alternativa ho provato anche

#pragma once

ma con lo stesso risultato.

Sicuramente sto sbagliando qualcosa io...

Per quanto riguarda la struttura cartelle, ho una cartella "src" che conteneva originariamente "LibA.h/.cpp" e "header.h", nella quale ho aggiunto "LibB.h/.cpp"

Può causare problemi?

No, non credo.

Controlla meglio, perché io uso spessissimo dei file condivisi tra diverse librerie e/o file sorgenti e ti assicuro che funziona.

Guardando bene gli errori, io nel file header ho questo

#define f32 float
#define s32 int
#define u32 unsigned int
#define u16 unsigned short
#define s8 char
#define u8 unsigned char

e gli errori sono tipo questi, quindi relativi ad esempio a unsigned e non a u8

error: duplicate 'unsigned'
#define u8 unsigned char

A parte la poca utilità di ridefinire tipi di variabili quando già esistono i tipi standard "brevi"


int8_t
uint8_t
int32_t
uint32_t 
etc etc

hai guardato bene gli errori, ma non quanto ti avevo suggerito di fare :wink:

Se il tuo file lo definisci in questo modo, lo puoi includere quante volte vuoi nelle classi dove ti serve.

#ifndef MY_HEADERS_H
#define MY_HEADERS_H

#define f32 float
#define s32 int
#define u32 unsigned int
#define u16 unsigned short
#define s8 char
#define u8 unsigned char

#endif

Si immagino non sia molto utile, però visto che negli "struct" ci sono infiniti riferimenti a queste variabili, avrei lasciato così...

Ho fatto come mi hai detto, ma per qualche motivo sembra ignorarlo..

Ecco il file "forza.h" (ho rimosso buona parte del contenuto per semplificarlo)
Se lo includo solo in "LibA.h" tutto funziona regolarmente, se lo includo anche in "LibB.h" mi da gli errori di cui sopra...

#ifndef FORZA_H
#define FORZA_H

#define f32 float
#define s32 int
#define u32 unsigned int
#define u16 unsigned short
#define s8 char
#define u8 unsigned char

struct Engine
{
    f32 MaxRpm;
    f32 IdleRpm;
    f32 CurrentRpm;
};

struct Car
{
    s32 Ordinal;          // Unique ID of the car make/model
    s32 Class;            // Between 0 (D - lowest) and 7 (X class - highest) inclusive
    s32 PerformanceIndex; // Between 100 (lowest) and 999 (highest) inclusive
    s32 DrivetrainType;   // 0 = FWD, 1 = RWD, 2 = AWD
    s32 NumCylinders;     // Number of cylinders in the engine
};

typedef struct _Telemetry
{
    struct Engine Engine;                                         // RPM values from the engine
    struct Car Car;                                               // Car specific info like specs and metadata
    f32 Speed;                                                    // Speed in meters per second
    f32 Power;                                                    // Power in watts
    f32 Torque;                                                   // Power in newtons/meter

} Telemetry;

#endif

Sembra come se alla seconda inclusione non trovasse "FORZA_H" e tentasse di includere di nuovo il contenuto

Forse sarebbe meglio vedere il codice completo a questo punto...
Prova a mettere su un esempio di base su wokwi come questo che ho fatto io:

Proverò anche questo... nel frattempo però potrei aver omesso un dettaglio importante. Il tutto lo sto caricando su un ESP8266, di fatti l'errore menziona la libreria di questo chip

Documents\ArduinoData\packages\esp8266\hardware\esp8266\3.1.2/tools/sdk/include/c_types.h:46:29: note: in expansion of macro 'u16'

Allora stai cercando di ridefinire dei tipi che sono già stati definiti nel core ESP8266.
L'errore è chiaro: u16 già esiste nel file c_types.h

Ci ho pensato, ma se commento ad esempio la riga relativa a u16, poi mi dice che u16 non è definito...

E mi chiedo anche come mai se includo forza.h una sola volta, non ho problemi

Noi guarderemmo da qualche altra parte, non alle #define

Le #define sono gestite dal preprocessore; che, esplicitamente, accetta la ridefinizione di una macro, con, al massimo, un warning e non un errore, se per caso le due definizioni differiscono in maniera significativa
Che comunque la compilazione procede
E questo è voluto proprio per permettere a più header di definire le stesse macro

Quindi crediamo che il problema non sia nelle #define, ma da altre parti

Hai anche i file .cpp oltre ai .h?

Altra domanda:

Intendi che il programma andrebbe bene senza problemi

Strano ma forse indicativo
Nella libreria B tu "usi" effettivamente la libreria forza?

Usa la forza Luke, usa la forza...

Si includo forza.h (che non ha il rispettivo .cpp) perché appunto contiene gli struct che mi servono nella LibB

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