Hello
Techniquement, ça fonctionne mais sur le principe je ne partage pas trop l'avis de kamill.
Quand on crée une telle bibliothèque avec une fonction afficher(), l'objet LiquidCrystal devrait être déclaré uniquement à l'intérieur du .cpp, non accessible depuis le reste du programme.
eeaeea, je pense que tu as un problème d'approche de la conception de bibliothèques, et te conseille d'aborder tes questions sous cet angle.
De manière générale, une bibliothèque permet de regrouper des lignes de codes cohérentes entre elles, et de les encapsuler dans une boîte noire dont seules les primitives de manipulation de haut niveau sont accessibles via le .h
Les deux principaux objectifs visés sont :
- la réutilisabilité / factorisation du code : plusieurs programmes peuvent utiliser les mêmes composants logiciels
- maîtrise de la complexité globale d'un programme, en isolant / séparant ses différentes parties
Cette maîtrise passe par la mise au point et validation de chaque bibliothèque unitairement. Pour chaque bibliothèque créée, il est indispensable de créer aussi un programme spécifique, dans le but de valider le bon fonctionnement de toutes les primitives exposées dans le .h
Ainsi, un programme très complexe peut être décomposé en parties moins complexes, isolées dans des librairies et mises au point séparément avant d'être assemblées.
Autre point très important dans la maîtrise de la complexité globale : cela oblige à se poser la question des liens entre chaque partie du programme. Au final : quelles sont les données / fonctions qui doivent rester internes à la bibliothèque, et quelles sont celles qui doivent être exposées dans le .h
On appelle ça de l'urbanisation de code.
Il n'y a rien de pire qu'un programme principal mono bloc, avec plein de fonctions non hiérarchisées qui s'appellent les unes les autres dans tous les sens, et un gros paquet de variables globales au milieu. Horreur de mise au point, bugs résiduels et effets de bord garantis à chaque fois qu'on veut le modifier.
Maintenant pour revenir dans le concret, prenons LiquidCrystal.h :
Celle-ci définit une classe, avec toutes ses méthodes, mais sans aucune instance.
C'est un peu différent de certaines bibliothèques qui définissent à la fois la classe et une instance de cette classe, car celle-ci a vocation à être unique dans le programme (exemples : Wire, Serial, ...).
Le code qui utilise LiquidCrystal.h (programme principal ou bibliothèque) doit créer lui-même une instance de la classe.
Usuellement LiquidCrystal.h est appelée par le programme principal, où on trouve un objet créé en variable globaleLiquidCrystal lcd(...);
Et cela convient car la classe LiquidCrystal apporte toutes les fonctionnalités de base permettant de manipuler un lcd.
Quelles pourraient être les raisons de vouloir utiliser LiquidCrystal depuis une bibliothèque ?
Si c'est juste pour urbaniser un programme complexe, le modèle serait d'avoir une bibliothèque gestionLCD.h.
Celle-ci pourrait par exemple contenir la déclaration de l'objet LiquidCristal dans son cpp, et exposer juste quelques méthodes dans le .h : allumer, éteindre, déplacerCurseur, afficher, etc.
Et aucune autre partie du code (programme principal ou autres bibliothèque) ne devrait avoir besoin d'accéder directement à l'objet LiquidCristal.
Tout doit passer via gestionLCD.h
Au passage, cette manière de procéder peut s'avérer fort judicieuse le jour où on veut changer le modèle d'écran LCD.
L'autre raison principale serait de vouloir ajouter des fonctionnalités à celles proposées par LiquidCrystal, et d'en faire profiter tous ses programmes.
Par exemple, on pourrait souhaiter ajouter une couche logicielle qui affiche proprement les caractères accentués et autres caractères spéciaux non gérés en natif par le controleur HD44780 (dont le caractère °, souvent nécessaire pour afficher une température), chose que je me suis déjà amusé à faire.
Cela permettrait de mettre à disposition une fonction println(), qui analyse le contenu de la chaîne à afficher, et utilise les 8 caractères personnalisables du lcd pour afficher les caractères spéciaux (mise à jour de la CGRAM à la volée, substitution de caractères entre ce qui est reçu et ce qui est transmis au lcd, etc.).
Dans mon cas, je me suis même amusé à appliquer cette mécanique pour le caractère g, dont l'affichage par défaut est vraiment trop moche.
On peut ainsi gérer des dizaines de caractères spéciaux, avec cependant la contrainte de ne pouvoir en afficher que 8 simultanément.
Pour ton second point, si une primitive d'une bibliothèque a besoin d'avoir beaucoup de données diverses en entrée, c'est souvent lié à une définition imprécise des objets manipulés.
Tu cites le cas de 6 variables + 2 tableaux à passer en paramètre d'une fonction.
Mais j'imagine que toutes ces données ont un rapport entre elles.
Si c'est bien le cas, la bonne approche est de définir la fonction et le modèle de données qu'elle manipule (une classe, un struct, ... ) dans la même bibliothèque.
Le programme principal instancie une occurrence de ce modèle, en tant que variable globale, et le passe en paramètre d'appel de la fonction.
Pour aller plus loin dans l'analyse de tes questions, il est vraiment nécessaire que tu détailles le pourquoi du comment de ce que tu souhaites faire, de manière très concrète. Je pourrai alors t'aider d'avantage