Vérifier si une instance de bibliothèque est déclarée

Bonjour,

Comment puis-je vérifier si une instance de bibliothèque à été déclarée ?

Dans l’exemple ci-dessous, j’aimerais imprimer OUI si [simpleBouton bouton2(26) ] et déclaré
ou NON si il est commenté.

librairie simpleBouton.h exemple_08_deux_boutons

//exemple_08_deux_boutons librairie simpleBouton.h
//Affichage de l'état de deux boutons
#include "simpleBouton.h"

simpleBouton bouton1(25);
//simpleBouton bouton2(26);
//Cablage : pin---BP---GND

void setup()
{
  Serial.begin(115200);

  #ifdef simpleBouton bouton2   //Ne fais rien
    Serial.println("Bouton2 défini")
  #endif
  
  if(simpleBouton::bouton2){    //Compilation error: 'bouton2' is not a member of 'simpleBouton'
  //if(bouton2){                  //si existe: renvoie Non,si n'existe pas: Compilation error: 'bouton2' was not declared in this scope
    Serial.println("Bouton2 OUI");
  }
  else {
    Serial.println("Bouton2 NON");
  }
}

void loop()
{
  // bouton1.actualiser();
  // bouton2.actualiser();

  // if (bouton1.vientDEtreEnfonce()) Serial.println("Bouton 1 Enfonce");
  // if (bouton1.vientDEtreRelache()) Serial.println("Bouton 1 Relache");
  // if (bouton2.vientDEtreEnfonce()) Serial.println("Bouton 2 Enfonce");
  // if (bouton2.vientDEtreRelache()) Serial.println("Bouton 2 Relache");
}

La directive #ifdef ou #if defined au niveau du préprocesseur peut savoir s une variable est existante (déclarée) ou non.
On peut faire:

#ifdef(simpleBouton bouton2)
  Serial.print("OUI");
#else
  Serial.print("NONI");
#endif

Le précompilateur enlève alors une des deux instructions.

On utilise #ifdef si on n'a qu'un élément à tester, #if defined(... si on a plusieurs conditions, par exemple

#if defined(simpleBouton bouton1) || defined (simpleBouton bouton2)
...

Avec les paranthèses, le compilateur me retourne une erreure:

 exit status 1

Compilation error: macro names must be identifiers

avec : #if defined (simpleBouton bouton1)
le compilateur retourne:

exit status 1

Compilation error: missing ')' after "defined"

sans les paranthèses, il dit tous le temps que l'instence n'existe pas.

PS: j'utilise un ESP32

Bonjour,

Pour que #ifdef nom soit vrai il faut que nom ait été défini dans un #define (ou dans la ligne de commande)
Il est donc impossible de savoir si une fonction a été définie par un #ifdef en donnant sont nom dans le #ifdef.

Il faut faire l'inverse c'est à dire définir la fonction si le nom est défini (par un #define)

#ifdef AVEC_CAPTEUR
void fonction() {/*...*/};
#endif

Ensuite on peut tester ce nom (par exemple avec #ifdef) dans la suite du programme pour savoir si la fonction existe.

Donc, si j'ai bien compris, il n'est pas possible de vérifier si l'instance à été créée. Je suis obligé de reseigner le programme des instances créées pour en suite avoir une valeur à tester.

Non pas directement.

il faut conditionner la création de l'instance par le test de définition d'une variable qui sera définie (ou non) par un #define. On peut ensuite tester cette variable par des #ifdef.

Ok.

MERCI, salutations et bonne fin de journée

effectivement @kamill a raison.

Je me demande si on ne pourrait pas gérer le problème différemment en faisant un tableau d'instances et en testant la taille du tableau avec un sizeof().

on peut aussi créer l'instance par new, et travailler avec le pointeur:

SimpleBouton* bouton2 = NULL;
bouton2 = new SimpleBouton ( ... ); // ligne à commenter ... ou pas
.../...
if ( bouton2 != NULL ) {
 // ici bouton2 existe
}

Ca marche :

//Exemple 08 librairie simpleBouton.h Modiffié
#include "simpleBouton.h"

simpleBouton* bouton1; // = NULL;
simpleBouton* bouton2 = NULL;
simpleBouton* bouton3 = NULL;
//Cablage : pin---BP---GND

void setup()
{
  Serial.begin(115200);

  //Initialiser les boutons
    //bouton1 = new simpleBouton (36);
    bouton2 = new simpleBouton (39);
    //bouton3 = new simpleBouton (34);

  //Tester les Boutons
    if(bouton1 != NULL) {Serial.println("bouton1 existe");}
      else {Serial.println("bouton1 n'existe pas");}
    if(bouton2 != NULL){Serial.println("bouton2 existe");}
      else {Serial.println("bouton2 n'existe pas");}
    if(bouton3 != NULL){Serial.println("bouton3 existe");}
      else {Serial.println("bouton3 n'existe pas");}
}

void loop() { /*...*/ }

Par contre à la fin du pointeur, le " = NULL " , il est obligatior ?
par-ce-que j'ai aussi essayé avec un tableau de pointeur :

simpleBouton* bouton[5];// = NULL;

est là avec le " = NULL" à la fin ça ne passe pas !
Salutations, bon week-end.

A partir du moment où la déclaration est globale (en dehors des fonctions), les valeurs sont automatiquement initialisées à ZÉRO par le startup.

Sinon on peut le faire à la main :
simpleBouton* bouton[5] = {NULL, NULL, NULL, NULL, NULL};
Mais c'est inutile, le résultat est le même.

On peut se reposer sur le compilateur pour initialiser des trucs à zéro, ou autre chose.
Mais c'est quand m^me beaucoup mieux de le faire explicitement, ça montre une intention (je veux qu'il soit nul, alors je l'écris). Pour ce que ça coûte !
simpleBouton* bouton1 = NULL;

Si j'écris
simpleBouton* bouton1;
ça veut dire : je crée une variable et je me fous de sa valeur. Je l'affecterai plus tard.

Oui et celà préviens de problème potentiel si le code est porté sur un autre compilateur, qui ne fait pas l'initialisation "inutile"

Donc si je crée par un tableau de pointeurs, je peux ajouter le "=NULL" avec un for{} dans le "setup()" avant de déclarer les objets (bouton).

...
const uint8_t nombreBoutons = 5;  //nombre d'emplacements disponibles pour les boutons
simpleBouton* bouton[nombreBoutons];

void setup(){
  //Renseigner les variables boutons
    for (uint8_t i = 0; i < nombreBoutons; i++) {
      bouton[i] = NULL;
    }
  //Initialiser les boutons   >>> A positionner après avoir renseigner les variable à "NULL" <<<
    bouton[0] = new simpleBouton (7);
    //bouton[1] = new simpleBouton (8);
    bouton[3] = new simpleBouton (9);
    //bouton[4] = new simpleBouton (11);
...

Pas besoin de for :

Pour autant qu'il y est toujours 5 emplacement. Là si je change [nombreBouton] tous suit.

Là on ne va pas être d'accord.

Si l'on déclare X variables globales sans les initialiser, le startup initialise automatiquement (section BSS) ces variables à ZERO, un memset(), et cela ne coûte rien.

Si l'on déclare X variables globales en les initialisant, le startup effectue une recopie d'une section constante en FLASH dans la section DATA en RAM.
Cela coûte plus cher, car d'une part cela occupe un espace en FLASH, et d'autre part cela prend du temps.

Cela n'a rien à voir avec le compilateur, seul le code du startup est responsable de l'initialisation des variables globales.

Je ne parle pas de ça!

Avec un memset() :
memset(bouton, 0, sizeof bouton);
Ça le fait aussi.