Go Down

Topic: Object name to String (Read 7458 times) previous topic - next topic

leo72

No, credo che lui voglia il nome dell'istanza creata.

una volta dichiarato un oggetto della classe Servo con:
Quote
Servo MyServo;


mi servirebbe poter stampare il nome dell'oggetto, quindi a livello logico dovrei fare:
Quote
x=nome oggetto;
serialprint (x);
ricevere in stampa: MyServo



Se ho capito, tu faresti:
Code: [Select]
Servo myServo;
x = myServo;
Serial.print(x); ==> myServo


nid69ita

#16
Feb 12, 2014, 10:08 am Last Edit: Feb 12, 2014, 10:16 am by nid69ita Reason: 1
dove x però è a sua volta un oggetto Servo, spero. Altrimenti non ho capito io cosa vuol fare.  :D
Se invece x è il ritorno di un qualche valore dell'oggetto MyServo/classe Servo, non puoi fare nulla
Perchè la return della attach()
Code: [Select]
return this->servoIndex
è semplicemente l'indice del vettore servos dichiarato static interno alla classe dei servo
Code: [Select]
static servo_t servos[MAX_SERVOS];

Ogni object di tipo Servo si riserva una cella in questo vettore. Questo è il significato di quel ID.
E servo_t è solo una struct con dentro una ulteriore struct con info quali numero pin, se attivo, e ticks. E null'altro.
my name is IGOR, not AIGOR

leo72

Appunto... su un microcontrollore, a che gli serve sapere come si chiama l'istanza di un oggetto? :smiley-surprise:

Maurotec



Sempre in quel link, per la classe usa:
Code: [Select]
typeid(myServo).name()
Ma anche questo dipende dal compilatore. Nel link parlano (sembra) di gcc, sarebbe da provare.


Provato ora di pranzo:
Code: [Select]
#include <Servo.h>
#define GET_NAME(x) #x
Servo MyServo;

void setup()
{ delay(1000);
 Serial.begin(9600);
 Serial.println( GET_NAME(MyServo) );
 Serial.println( typeid(MyServo).name() );           //error
}

void loop(){}

La macro okay (ritorna il nome dell'oggetto).
Per la typeid,  il compilatore dà errore:
 sketch_feb11a:9: error: cannot use typeid with -fno-rtti
perchè un parametro passato al compilatore ne impedisce l'uso. Probabilmente per rendere l'eseguibile più leggero vengono eliminate le informazioni dei tipi/classi/etc. a runtime. (Almeno credo)

EDIT: da sito GCC:
"-fno-rtti
Disable generation of information about every class with virtual functions for use by the C++ runtime type identification features (`dynamic_cast' and `typeid'). If you don't use those parts of the language, you can save some space by using this flag. Note that exception handling uses the same information, but it will generate it as needed."


mmmmm...nid o nid che stai a dì ]:). -fno-rtti funziona solo sul PC o su piattaforme su cui si possono usare le shared lib. Quindi su un PC quel parametro evita di ritornare informazioni dinamiche per mezzo della libreria shared rtti.

Su arduino e in genere su avr8 e simili il linguaggio C++ non può far uso di librerie rtti o meglio non esistono le shared lib. In via del tutto !!!teorica!!! potresti ricompilare gcc per avr abilitando rtti che dovrà essere statica (di suo non lo è) e quindi poi ti ritroveresti parte del codice rtti nel firmware, ma ciò non è stato pensato.

Se testato, (come giustamente chiedeva leo) ci dice il motivo per fare ciò, ci troviamo un workaround (o almeno ci proviamo). Quindi a che ti serve, cosa volevi fare ecc.?

Ciao.

nid69ita


mmmmm...nid o nid che stai a dì ]:). -fno-rtti funziona solo sul PC o su piattaforme su cui si possono usare le shared lib. Quindi su un PC quel parametro evita di ritornare informazioni dinamiche per mezzo della libreria shared rtti.
Su arduino e in genere su avr8 e simili il linguaggio C++ non può far uso di librerie rtti o meglio non esistono le shared lib.

L'errore  sketch_feb11a:9: error: cannot use typeid with -fno-rtti
me lo ha dato il compilatore (anzi l'IDE Arduino),  quindi deduco che al gcc Arduino passa quel parametro. Poi se non lo passa e il gcc sapendo di non avere librerie shared rtti mi dà quel msg, è il compilatore che mi mette su cattiva strada nel cercare il motivo di un simile msg  :smiley-mr-green:
my name is IGOR, not AIGOR

testato

scusate se insisto, ma altrimenti non sarei Testato  :), ma perche' devo rispondere a delle domande quando ho postato lo sketch completo ?
Non voglio credere che ho scritto una funzione troppo complicata per essere capita da voi e quindi dover rispondere a domande. Lo sketch e' autoesplicativo, cosa io voglio che venga stampato lo si evince dallo sketch stesso, quindi non ve lo dico, ma ve lo riposto per non farvelo andare a ritrovare  :smiley-mr-green:

Code: [Select]
#include <Servo.h>
Servo MyServo;

void setup() {
 Serial.begin(115200);
 MyServo.attach(7);
 Test_Servo(MyServo);
}

void loop() {}

void Test_Servo(Servo x)
{
 delay(2000);
 x.write(50);
 Serial.println (x);
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Maurotec

Quote
scusate se insisto, ma altrimenti non sarei Testato  smiley, ma perche' devo rispondere a delle domande quando ho postato lo sketch completo ?


grrrr, ciò è molto irritante.  ]:)

Ah si, mo ti cionco le dita.

Ma in C++ normalmente non si passano i parametri per valore, per di più tu passi per valore un oggetto grande sullo stack per far cosa? Tempo e risorse sprecate.
Prendi il fottuto manuale C++ e studiatelo  :smiley-mr-green: :smiley-mr-green:

Code: [Select]

void Test_Servo(Servo &x) // passiamo un alias che è meglio
{
  delay(2000);
  x.write(50);
  Serial.println (x);


La classe Print ha un metodo polimorfico di nome println che prende come argomento un oggetto di tipo/classe Servo? No non c'è l'ha e da qui viene fuori l'errore a tempo di compilazione.

Soluzione:
Eredita la classe print eredita la classe Servo. Alla tua print aggiungi un metodo println(const Servo &servo).
Nella tua classe Servo crea un metodo che stampa quello che vuoi tu in base al codice contenuto, di nome print.
Da println(const Servo &servo) richiami il metodo MyServo::print con servo.print() e hai risolto.

Rimane ancora da capire, cosa vuoi che stampi println?
Il nome dell'oggetto? Non esiste il nome in C++, dopo compilato diventa un indirizzo
Il nome del tipo? Non esiste in C++ il nome del tipo, perché dopo compilato non esiste neanche il tipo. :)

Mi sembra che è un bel risparmio di risorse, ciò che non c'è non occupa spazio, e comunque se serve si aggiunge.

Ciao.

testato

grande  :)

si volevo il nome dell'oggetto, cioe' in questo mio sketch volevo stampare "MyServo".

Quindi mi stai dicendo se ho capito che posso pure non studiare i due anni che mi hai assegnato nella prima parte del tuo messaggio (creare nuovi metodi di classi che conosco solo di vista ed anche poco  :)) perche' cmq non posso stampare il nome dell'oggetto ?
ti riquoto per chiarezza:
Quote
cosa vuoi che stampi println?
Il nome dell'oggetto? Non esiste il nome in C++, dopo compilato diventa un indirizzo
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Maurotec

Bravo, ogni scusa è buon pretesto per non studiare, e anche questa volta l'hai scampata.
Il tipo potresti anche stamparlo, in quando la classe servo può sapere come si chiama, basta aggiungere un membro const char className[] = "Servo"; creare un metodo dentro "Servo" const char *typeName() { return className; }

Ma per il nome di una variabile proprio non è possibile, se non nel modo in cui ti ha suggerito nid.
Però se consideri un oggetto come un qualcosa composto da attributi allora il nome dell'oggetto devi
fornirlo tu e in tal caso puoi risalire al nome, ma l'oggetto non ha percezione di se.
Pensa pensa forse ciò è impossibile anche in C++ con rtti, però chissà con le eccezioni abilitate qualcosa si può, peccato che non le uso mai e mi scoccia indagare.

In java o python ciò è fattibile e dovrebbe fare parte di quello che chiamano "introspezione", almeno credo per python ricordo si, per java potenzialmente pure e figurati se non l'hanno implementato.

Ora che ho capito che vuoi stampare il nome di una variabile mi chiedo anche qual'e il fine?
Alcune cose che fai in java non puoi farle in C++, e alcune cose che fai in C++ non puoi farle in java es non puoi programmare il microcontroller 2560 in java, però però se si potesse compilare il sorgente java in binario (gcc lo fa) tu forse ne trarresti vantaggio, ma bisogna vedere di quanto ingrassa firmware.

Ciao.

leo72

@Testato:
al mio reply #15 lo avevo capito quello che volevi:

No, credo che lui voglia il nome dell'istanza creata.


Ma più sotto ho anche aggiunto:

su un microcontrollore, a che gli serve sapere come si chiama l'istanza di un oggetto? :smiley-surprise:


Quindi, che te ne fai di sapere come si chiama quell'oggetto?
Non vuoi rispondere? Tieniti il problema per te...  :smiley-yell: :smiley-yell:


testato

Sei fortunato, ora ho voglia di rispondere  XD

La funzione che ho scritto, con la quale in questo caso passo solo il nome dell'oggetto, mi passa altri argomenti, come 3 posizioni diverse del servo, ed i ms di delay tra un movimento e l altro. Visto che i servo sono 12 con una sola funzione li gestisco tutti (e qui ti ho citato perché ho ricordato il post dove mi spronasti a creare funzioni con argomenti invece di multiple procedure senza argomenti e void come facevo io.)
A questo punto vedendo che la funzione "funziona", anche se ora Mauro ha spiegato che è inutilmente pesante passare come argomento un oggetto Servo, avevo pensato semplicemente di mettere un println nella funzione per avere conferma dell esecuzione di tutti i movimenti ad uno ad uno dei 12servo. Visto che passavo il nome oggetto servo cosa di piu comodo ed esplicativo potevo stampare ? A questo punto devo passare un ulteriore argomento alla funzione per identificare il nome del servo, era un idea per risparmiare una variabile ed evitare di aggiungere un argomento alla funzione. Avere li davanti agli occhi il nome che ti serve stampare, e non poterlo stampare, mi ha fatto aprire questo topic, che spero utile anche ad altri.
Vi ringrazio, karma per tutti :-)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Maurotec

Sei sfortunato, io ora non ho voglia di illustrarti la soluzione.  ]:D

Vebbè, dai ma solo un accenno, e te lo devi fare bastare.

Code: [Select]

#define SERVO_T const char *name, const Servo &servo

#define OBJ_SERVO(_servo) "MyServo", _servo

void funct(SERVO_T)
// SERVO_T expand to const char *name, const Servo &servo
{
     Serial.Println(name);
     servo.write(50);
}

void loop() {
      funct( OBJ_SERVO(MyServo) );
      // OBJ_SERVO expand to "MyServo", MyServo
}


Se ci riesci puoi includere in OBJ_SERVO anche la stringfy di nid.

Ma c'è ne sono altre di soluzione e che ti devi studiare il fottuto ...e anche quello del C, e purtroppo non basta.

Ciao.



testato

ho trovato un vecchio libro del C, di Hancock e Krieger, "Il Linguaggio C", roba del 1986, tradotto in italiano 10 anni dopo, e' roba buona ?
Prometto che lo leggero'  :)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Maurotec

Non conosco quel libro, ma sicuramente è meglio di niente.
Tieni in considerazione che si riferisce a prima dello standard 1999, e quindi è il vecchio C ansi che non ti permette
di scrivere: for(int i = 0; ecc perché la dichiarazione di i deve essere fuori dal for.

Per le struct, typedef, funzioni, puntatori ecc non ci dovrebbero essere grandi differenze.

In italiano non c'è molto da leggere, e quel poco che si trova in giro non è a mio parere sufficiente.
Comunque sai che puoi postare domande e riceverai risposte più comprensibili se hai un background di conoscenze sul C/C++. Per il C++ ti servono le classi es per il tuo problema potresti creare una tua classe che si inventa un nome e lo salva in una variabile privata a cui tu puoi accedere usando il metodo (che devi creare) char *getName(), che restituisce un puntatore ad una area di memoria in cui c'è salvata l'array di caratteri, stessa area di memoria in cui risiede la variabile privata che hai usato dentro la classe per mantenere il nome.

Potresti fare in modo che quando crei instanza della tua classe il nome sia "Servo" i il valore di una variabile statica che viene incrementata ogni volta che crei una istanza, per cui avresti "Servo0", "Servo1", "Servo2" ecc. Questa tua classe può o meno ereditare la classe Servo.

Ciao.

gpb01


In italiano non c'è molto da leggere, e quel poco che si trova in giro non è a mio parere sufficiente.


Beh ... oddio ... c'è il Testo Sacro ...  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up