dove pinSize è il numero di elementi che andrò a memorizzare (in questo caso 2)
e valorizzo con :
int i = 0;
for (JsonObject aa : pin)
{
retGpio[i].gpio = aa["gpio"] ;
retGpio[i].stato = aa["stato"].as<String>(); ;
retGpio[i].time = aa["time"] ;
i++;
}
ora sono in difficoltà su come restituire i dati.
immagino di non poter definire la funzione come outGpio (nome struct) visto che sono più elementi, ma dover utilizzare i puntatori, quindi outGpio*
Ma neppure cosi puoi.
La variabile/array "retGpio" che crei nella funzione, ha vita solo dentro alla funzione (non è in memoria globale). Quando la funzione esce, tutto quel blocco di dati viene distrutto. Se fai return di quel puntatore, quello punterà... a una zona di memoria distrutta (deallocata).
Secondo me puoi:
creare l'array "retGpio" fuori dalla funzione e passarlo alla funzione come parametro (ma forse a priori non sai quanti elementi ci sono)
dentro la funzione usi allocazione dinamica usando new (e quindi allochi l'array in spazio memoria globale) e poi fai return del puntatore.
confermo che a priori non so quanti elementi possano esserci.
ho provato la soluzione che dell'allocazione dinamica, ma probabilmente ho sbagliato qualcosa.
ora ci riprovo.
(normalmente utilizzo PHP, ho bisogno di tempo per entrare nell'ottica dei dati C)
le String sono oggetti ed è difficile con new calcolare lo spazio corretto della struct di cui un elemento è un oggetto.
le String possono portare a problemi di spezzettamento di memoria.
Mi pare che se il tuo "stato" è un intero (dove ogni valore ha un significato) semplifichi di molto..
Poi, quando stampi, allora converti quel valore in testo adeguato.
dovrai cambiare qualcosa qui: retGpio[i].stato = aa["stato"].as<String>();
Tu sai quali valori testo possono esserci ? sono "on" e "off" ?
Non ho ben capito perché impelagarti nel restituire una struct, o un suo puntatore, o fare allocazioni dinamiche. Sarà che per mia formazione cerco sempre la soluzione più semplice e pratica...
Definisci l'array come globale (come ha suggerito anche @nid69ita) nel quale come numero di elementi magari imposti il numero massimo previsto (non sono mica infiniti...), e senza usare le famigerate "String" (basterebbe anche un solo char tipo "0" o "1" o direttamente come byte, in 0 o 1 per off e on ad esempio), poi alla funzione passi solo il json e con questo ti valorizza l'array e fai restituire il numero di elementi ricevuti (col quale poi estrarre i dati e fare quello che ti serve).
Esempio:
const int PINSIZE = 8; // Massimo numero di elementi
struct outGpio
{
int gpio ;
bool stato ;
int time ;
} retGpio[PINSIZE] ;
...
int caricaDati()
{
int i = 0;
for (JsonObject aa : pin)
{
retGpio[i].gpio = aa["gpio"] ;
retGpio[i].stato = (aa["stato"] == 1);
retGpio[i].time = aa["time"] ;
i++;
if (i == PINSIZE) break;
}
return i;
}
E' bene iniziare sempre dalle cose più semplici e che si sanno gestire. Altrimenti rischi di scadere nella "Sindrome di Gundam"
Prova il metodo che ti ho indicato e vedrai che è tutto più semplice, poi potrai provare altro.
Per dirtelo dovresti mostrarci il tuo codice o almeno un codice che fa qualcosa del genere (es. il Json lo inserisci in una stringa costante invece di leggerlo) e che possiamo prendere, copiare e provare autonomamente.
Senza questo, stiamo parlando di cose talmente generiche che non ci sono possibili risposte per te utili.
Posta almeno un pezzo di codice. return retGpio*; Non ha senso
E' normale return retGpio; a meno che retGpio non è fuori dalla funzione oppure stai usando nomi di variabili diverse (ti ricordo che il C è case-sensitive, Pippo è diverso da pippo)
Inoltre una cosa... ma pinSize da dove esce ? E' fisso ?
Se viene calcolato dal json dentro alla tua funzione e quindi è variabile di volta in volta, e quindi viene "calcolato" dentro a outputTemp(), beh... dovrai restituire anche questo valore (puoi avere un parametro modificabile ad esempio)
int numpin=0;
...
array=outputTemp(&numpin); // numpin modificato dalla funzione, passato come puntatore a int
Vuoi restituire un array di struct da una funzione in C++ (Arduino). Ci sono vari modi per farlo, ma bisogna fare attenzione alla memoria, specialmente su microcontrollori con RAM limitata come ESP32 o AVR.
Allocazione dinamica + puntatore
Definisci la struct fuori dalla funzione:
Struct outGpio {
int gpio;
String stato;
int time;
};
Scrivi la funzione che restituisce un outGpio* (array dinamico):
outGpio* parseJsonAndReturnArray(String jsonStr, size_t& size) {
// Parsing JSON (usiamo ArduinoJson)
StaticJsonDocument<512> doc;
DeserializationError error = deserializeJson(doc, jsonStr);
if (error) {
Serial.println("Errore nel parsing JSON");
size = 0;
return nullptr;
}
JsonArray pinArray = doc["pin"];
size = pinArray.size(); // numero di elementi
// Allochiamo dinamicamente un array
outGpio* result = new outGpio[size];
int i = 0;
for (JsonObject obj : pinArray) {
result[i].gpio = obj["gpio"];
result[i].stato = obj["stato"].as<String>();
result[i].time = obj["time"];
i++;
}
return result;
}
Si tratta di una "raw literal string".
La differenza principale è che quando il compilatore la incontra, ignora tutti i caratteri che necessitano dell'escape come le virgolette \", ma anche ad esempio i caratteri di fine riga e ritorno a capo (\n\r).
Questo ti consente (tra le altre cose) di definire delle stringhe anche andando a capo senza doverti curare di quello che c'è in mezzo aumentando cosi la leggibilità del codice.