La programmation peut-être très très souvent adapté à la vie réelle. Et ici, encore une fois, je vais pouvoir sortir un exemple de la vie courante, pour aider à mieux comprendre le principe des signaux.
Mais globalement, les signaux permettent d’émettre des messages vers une méthode (d’une classe ou non) pour signaler quelque chose, donc, travailler avec des évènements, au travers des boost::signal<>
et sigc::signal<>
! :)
L’exemple de la vie courante
Imaginez que vous commandiez une pièce, pour votre voiture, à votre garagiste.
Soit le garagiste vous donne le délai et vous attendez ce délai quoi qu’il arrive, soit vous lui demandez qu’il vous appelle quand la pièce est prête.
Le garagiste va donc vous appeler / vous transmettre un message / vous signaler que le moment attendu ( La pièce est prête ) est arrivé.
Là, les signaux vont vous permettre de faire la même chose.
Vous créez un signal, pour annoncer que quelque chose de bien définis vient de se produire ( le signale à été appelé ), et émettez ce signal à la fonction connecté à ce signale.
Par exemple, vous pourriez créer un signal qui émettrait lorsqu’un booléen change d’état, ou encore lorsqu’une méthode de la classe à été appelé etc …
Les outils à disposition pour coder un signal
Pour coder vos signaux, il existe 2 Framework ( sous entendu, très connu ) :
La manière de coder des signaux, avec les deux Framework, est très proche. Donc, pour faire votre choix, si vous utilisez l’un des deux, autant continuer avec, pas la peine d’alourdir vos dépendances pour rien.
Passons au code !
Comme je l’ai dis juste avant, coder les signaux est très similaire pour ces deux Framework. Donc, je vais vous montrer la syntaxe pour les deux simultanément pour les deux cas.
Inclusion
GTKmm:
1
#include <sigc++/sigc++.h>
Boost:
1
#include <boost/signal.hpp>
Déclaration d’un signal
Dans les deux cas, il faut déclarer le signal. Cette étape permet de définir le typage des arguments que le signal pourra passer lorsqu’il sera émit.
Déclaration d’un signal sans arguments
GTKmm:
1
2
3
4
public:
typedef sigc::signal<void> nomDuSignal;
protected:
nomDuSignal signalEmit;
Boost:
1
2
3
4
public:
typedef boost::signal<void()> nomDuSignal;
private:
nomDuSignal signalEmit;
Méthode attachable :
1
2
3
4
void MyClass::myMethod()
{
std::cout << "MyClass::myMethod() called !" << std::endl;
}
Déclaration d’un signal avec arguments
GTKmm:
1
2
3
4
public:
typedef sigc::signal<void, int> nomDuSignal;
protected:
nomDuSignal signalEmit;
Boost:
1
2
3
4
public:
typedef boost::signal<void(int)> nomDuSignal;
private:
nomDuSignal signalEmit;
Méthode attachable :
1
2
3
4
void MyClass::myMethod( int i )
{
std::cout << "MyClass::myMethod(" << i << ") called !" << std::endl;
}
Je trouve plus clair la version Boost.
Connexion du signal
Maintenant que notre signal est déclaré, ainsi que la méthode recevant le message émit, il nous faut les connecter ensemble !
Pour se faire, il faut créer une méthode dans la classe émettant le signale, qui va retourner la connexion établie, et ceux dans les deux cas: GTKmm et Boost.
Écrivons cette méthode:
GTKmm:
1
2
3
4
Emiter::nomDuSignal Emiter::signalEmitor()
{
return signalEmit;
}
Boost:
1
2
3
4
boost::signals::connection Emiter::connect(nomDuSignal::slot_function_type subscriber)
{
return signalEmit.connect(subscriber);
}
Puis il ne reste plus qu’à connecter.
Connexion du signal sans arguments
GTKmm:
1
instance_classe.signalEmitor().connect( sigc::ptr_fun( &nomMethod ) );
Boost:
1
instance_classe.connect( boost::bind( &nomMethod ) );
Connexion du signal avec arguments
Là GTKmm ne change pas la manière de connecter le signal, mais par contre, elle change pour Boost.
Boost:
1
instance_classe.connect( boost::bind( &dir, _1 ) );
Il faut rajouter une représentation des arguments. _1
pour le premier, _2
pour le second etc…
Maintenant, si vous exécutez le signal, la fonction connecté au signal sera appelé ! :-)
Les exemples
Bien entendu, pour vous aider à comprendre tout ca, j’ai écris 2 mini projets, utilisant les signaux avec GTKmm puis avec Boost.
Les sources se trouvent dans ce depot Git sur Github.com.