IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

[Boost::bind] Cdecl / Callback


Sujet :

Boost C++

  1. #1
    Membre habitué
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Points : 186
    Points
    186
    Par défaut [Boost::bind] Cdecl / Callback
    Bonjour à tous

    Je me pose la question suivante (y'a des matins comme ça ) :

    Est-il possible de passer une fonction membre non static en paramètre d'une fonction, pour un appel de callback déclarée en "cdecl".
    J'utilise souvent ce mécanisme avec boost::function et boost::bind... Alors je me dis : ça ne coute rien d'essayer... (Ca serait pratique de pouvoir câbler ses callbacks de cette manière avec GLUT par exemple...)

    Résultat :

    Voici un code minimal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #define BOOST_MEM_FN_ENABLE_CDECL
     
    #include <boost/function.hpp>
    #include <boost/bind.hpp>
     
    class A {
    public:
     
      typedef boost::function<void(void)> CB1;
      typedef void ( _cdecl * CB2 )( void );
     
      void setCB1( CB1 cb ) { _callback1 = cb; } ;
      void setCB2( CB2 cb ) { _callback2 = cb; } ;
     
      CB1 _callback1;
      CB2 _callback2;
    };
     
    class B {
    public:
      void f(void) { } ;
      static void g(void) { } ;
    };
     
    int main(int argc, char* argv[])
    {
      A a;
      B b;
     
      a.setCB1( &B::g ); // OK
      a.setCB2( &B::g ); // OK
     
      a.setCB1( boost::bind(&B::f, &b) ); // OK
      a.setCB2( boost::bind(&B::f, &b) ); // Pas OK : ne compile pas !!!
    }
    Quelqu'un saurait me dire s'il y a une manière de faire ?
    Plus y'a d'Gruyère, plus y'a d'trous !
    Plus y'a d'trous, moins y'a d'Gruyère...
    Donc, Plus y'a d'Gruyère, moins y'a d'Gruyère !!!

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 58
    Points : 66
    Points
    66
    Par défaut
    J'ai fait a peu près le même test il y a quelques jours, et j'étais arrivé a la conclusion que c'etait pas possible...
    Mais si il existe une solution, ça m'intéresse aussi!

  3. #3
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Comment voudrais-tu faire passer un boost::function en tant que void (*)() ? Ce n'est absolument pas compatible au niveau des types, il faut que le callback soit pris en tant que boost::function.

  4. #4
    Membre habitué
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Points : 186
    Points
    186
    Par défaut
    Oui oui, j'ai bien vu que la conversion n'était pas possible, le compilo fait son caprice comme je m'y attendais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    c:\...\Source.cpp(35) : error C2664: 'A::setCB2'*: impossible de convertir le paramètre 1 de 'boost::_bi::bind_t<R,F,L>' en 'A::CB2'
            with
            [
                R=void,
                F=boost::_mfi::mf0<void,B>,
                L=boost::_bi::list1<boost::_bi::list_av_1<B *__w64 >::B1>
            ]
            Aucun opérateur de conversion définie par l'utilisateur disponible qui puisse effectuer cette conversion, ou l'opérateur ne peut pas être appelé
    Ma question est : est-il possible de passer f en callback (f membre non static de B) et si oui comment ? Je me demandais s'il existait un moyen de reproduire le mécanisme boost::bind/boost::function...
    Plus y'a d'Gruyère, plus y'a d'trous !
    Plus y'a d'trous, moins y'a d'Gruyère...
    Donc, Plus y'a d'Gruyère, moins y'a d'Gruyère !!!

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Ma question est : est-il possible de passer f en callback (f membre non static de B) et si oui comment ? Je me demandais s'il existait un moyen de reproduire le mécanisme boost::bind/boost::function...
    Ma réponse sous-entendait "non"

    Il ne faut pas inverser les rôles. C'est boost::function qui est suffisamment flexible pour accepter n'importe quel type de fonction, mais pas l'inverse. Un void(*)() n'acceptera qu'un void(*)(). Et comme ici le void(*)() n'existe nulle part, j'imagine mal qu'on puisse faire une quelconque conversion pour le rendre compatible.

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Ce que tu peux faire par contre c'est essayer de wrapper ce que propose tes libs pour les fonctions de façon à pouvoir te servir de boost::function.

  7. #7
    Membre habitué
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Points : 186
    Points
    186
    Par défaut
    Oky, ça n'est pas possible => j'ai la réponse à ma question... Merci beaucoup à vous tous pour vos commentaires

    Pour le wrapper je ne voit pas trop comment faire... je vais y réfléchire. En attendant je vais garder mes fonctions et variables static toutes moches, on va faire avec, tampis !
    Plus y'a d'Gruyère, plus y'a d'trous !
    Plus y'a d'trous, moins y'a d'Gruyère...
    Donc, Plus y'a d'Gruyère, moins y'a d'Gruyère !!!

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 58
    Points : 66
    Points
    66
    Par défaut
    Citation Envoyé par Laurent Gomila
    Comment voudrais-tu faire passer un boost::function en tant que void (*)() ? Ce n'est absolument pas compatible au niveau des types, il faut que le callback soit pris en tant que boost::function.
    ce serait théoriquement possible si boost::function implementait un operateur de cast comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    typedef void tCallback(void);
     
    class Pipo
    {
     
    public:
     
    	static void Mito(void)
    	{
    		cout<<"pipo mito!"<<endl;
    	}
     
    	operator tCallback* ()
    	{
    		return(Mito);
    	}
     
    };
     
    void MaFonction(tCallback *_pfFunction)
    {
    	(*_pfFunction)();
    }
     
    int Main()
    {
    	Pipo kPipo;
    	MaFonction(kPipo);
    }

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    ce serait théoriquement possible si boost::function implementait un operateur de cast comme ceci:
    Oui, mais comme je l'ai dit juste après, vu que la callback en tant que void(*)() n'existe nulle part, c'est impossible. Et c'est encore plus impossible de convertir un pointeur sur fonction membre en pointeur sur fonction non-membre.

    Pour le wrapper je ne voit pas trop comment faire...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Wrapper
    {
    public :
     
        static void OnDisplay()
        {
            DisplayCB();
        }
     
        static void SetDisplayCallback(boost::function<void()> Func)
        {
            DisplayCB = Func;
            glutDisplayCallback(&Wrapper::OnDisplay);
        }
     
    private :
     
        static boost::function<void()> DisplayCB;
    };
     
    Wrapper::SetDisplayCallback(boost::bind(&MaClasse::Display, MonObjet));

  10. #10
    Membre habitué
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Points : 186
    Points
    186
    Par défaut
    Merci Laurent pour l'exemple C'est beaucoup plus simple que je ne me l'imaginais... Je vais jouer un peu avec ça
    Plus y'a d'Gruyère, plus y'a d'trous !
    Plus y'a d'trous, moins y'a d'Gruyère...
    Donc, Plus y'a d'Gruyère, moins y'a d'Gruyère !!!

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Ce n'est pas possible avec GLUT car les fonctions ne prennent pas de paramètre void*.
    Boost ftw

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. utilisation correct de boost:bind et result_of
    Par guillaume07 dans le forum Boost
    Réponses: 3
    Dernier message: 02/11/2009, 15h13
  2. boost::bind et membre de classe
    Par Trunks dans le forum Boost
    Réponses: 2
    Dernier message: 20/10/2009, 08h58
  3. Télécharger et installer boost::bind
    Par Electroniktor dans le forum Boost
    Réponses: 6
    Dernier message: 16/06/2008, 13h08
  4. for_each + boost::bind = crash ?
    Par Patriarch24 dans le forum C++
    Réponses: 8
    Dernier message: 21/09/2007, 09h47
  5. Utilité de boost::bind ?
    Par swirtel dans le forum Boost
    Réponses: 5
    Dernier message: 07/09/2007, 16h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo