Bonjour,
Cela fait un moment que je coinçais sur un bug dans un gros programme. J'ai trouvé un bidouillage qui fait tout fonctionner, mais ce n'est pas satisfaisant. Voici une version très allégé de mon code (faite pour y comprendre un peu plus).
//--- Variable pointeur sur ma classe ---
class ClassTest; // Prédéfinition
ClassTest *pointeurSecret; // Il pointera sur l'instance de ma classe
//--- Classe de test --------------------
class ClassTest
{
public:
ClassTest(void); // Constructeur!
void (*functionExt)(void); // Une fonction externe de ma classe qu'elle peut appeler
};
ClassTest::ClassTest(void)
{
pointeurSecret=this; // Quand je crée l'instance, on peut y accéder par le pointeurSecret
}
//--- Une fonction externe --------------
void uneFonction(void)
{
// Elle doit faire n'importe quoi, cela n'a pas d'importance
// Elle va afficher le mot bonjour, suivi d'un numéro
Serial.println("Bonjour N°"+String(random(100)));
delay(500); // C'est pas la peine de remplir trop vite la console
}
//--- Fonction pour loop() --------------
void fonctionSecrette(void)
{
// Le pointeurSecret indique donc (si créée) une instance de ma classe
// Cette insstruction appelle la fonction externe de l'instance
// Cela va appeler uneFonction
// uneFonction affiche le mot bonjour
// En résumé, fonctionSecrète affiche bonjour (faut pas le dire au compilatuer)
(*pointeurSecret->functionExt)();
}
void setup()
{
Serial.begin(9600);
// Création de mon instance
ClassTest test; // Je la crée
test.functionExt=&uneFonction; // Je lui rajoute la possibilité d'accéder à une fonction externe
asm("nop"); // Très utile!
}
void loop()
{
fonctionSecrette();
}
Dans mon vrai code complet, mes classes sont des boutons, et l'utilisateur peut définir un comportement en surchargeant une méthode ou en utilisant une fonction externe.
Quand je compile cet exemple, cela fonctionne.
Mais si je retire le asm("nop"); le programme n'affiche plus rien. Après recherches, je me suis apperçu que la taille du code a diminuée, montrant que certaines instructions ont disparues de l’exécutable.
La ligne
ClassTest test;
peut se trouver un peu n'importe où, avant ou après start(), avant ou après Serial.begin, seule contrainte, c'est de la mettre avant
test.functionExt=&uneFonction;
Et c'est en déplaçant ces lignes que j'ai compris ce qu'il faut faire: la ligne
test.functionExt=&uneFonction;
ne doit pas se trouver en toute fin de start()!
un nop fonctionne comme le Serial.begin... Je m'en suis aperçu en mettant un Serial.println pour suivre une variable.
Mon problème est en partie résolu, je sais qu'il faut mettre quelque chose derrière test.functionExt=&uneFonction;, mais si le compilateur vire mon code parce qu'il croit que cette ligne ne sert à rien, je ne vois pas pourquoi un nop lui fait comprendre le contraire; En fait c'est le nop qu'il pouvait virer