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 ?

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 45
    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 : 40
    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...

  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 : 40
    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 861
    Points
    11 861
    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 !

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 45
    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 : 40
    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

  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*.

+ 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, 16h13
  2. boost::bind et membre de classe
    Par Trunks dans le forum Boost
    Réponses: 2
    Dernier message: 20/10/2009, 09h58
  3. Télécharger et installer boost::bind
    Par Electroniktor dans le forum Boost
    Réponses: 6
    Dernier message: 16/06/2008, 14h08
  4. for_each + boost::bind = crash ?
    Par Patriarch24 dans le forum C++
    Réponses: 8
    Dernier message: 21/09/2007, 10h47
  5. Utilité de boost::bind ?
    Par swirtel dans le forum Boost
    Réponses: 5
    Dernier message: 07/09/2007, 17h27

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