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.Function] Appeler une fonction "externe"


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut [Boost.Function] Appeler une fonction "externe"
    Salut à tous,

    Dans le cadre d'un travail en équipe, j'aimerais me servir d'une fonction membre utilisé par mon collègue, dont je n'ai pas besoin de connaitre le code source normalement.

    Voici ma fonction que j'aimerai créer (l'utilisation de Boost.Fonction est très certainement mauvaise):

    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
    void Camera::creerFilm(boost::function<void (vigra::UInt16Image & )> & fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
    	std::cout << "Generation d'un film en cours..." << std::endl;
    	std::ofstream file ( nom_fichier.c_str(), std::ios_base::binary);
    
    	for (int i = image_debut; i < image_fin; i++) {
    		if (isNumeroValide(i) ) {
    			vigra::UInt16Image image = getImage(i);
                            fonc(image); // Traitement à appliquer ICI
    			
    		
    			vigra::UInt16Image::const_iterator iter;
    			for (iter = image.begin(); iter != image.end(); iter++) {
    				file.write(reinterpret_cast<const char*>(iter), sizeof(vigra::UInt16));
    			}
    		}
    	}
    }
    J'aimerai recevoir un pointeur de fonction de sa part, fonction dont je ne connais pas a priori l'implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void applyTreatment(vigra::UInt16Image & image)
    {
       //Code
    }
    Comment bien utiliser Boost.Function? J'ai beau lire et relire la doc de Boost, je ne vois pas comment m'en servir ? C'est lui qui choisi la fonction à appliquer, et c'est moi qui possède l'argument (image).

    Comment faire?

    Merci de votre aide (encore une fois ! )

  2. #2
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    J'ai avancer un peu sur mon problème maintenant, j'ai un problème d'édition des liens que je n'arrive vraiment pas à résoudre:

    Camera.cpp :
    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
     
    class Foo;
     
    template <typename T>
    void Camera::creerFilm(boost::function<void (T*, vigra::UInt16Image & )> fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
    	std::cout << "Generation d'un film en cours..." << std::endl;
    	std::ofstream file ( nom_fichier.c_str(), std::ios_base::binary);
     
    }
     
    template <typename T>
    void Camera::genererFilm(boost::function<void (T*, vigra::UInt16Image & )> fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
    	boost::thread my_thread(boost::bind(&Camera::creerFilm, this,  fonct, image_debut, image_fin, nom_fichier));	
    }
    main.cpp:
    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 Foo
    {
    public:
    	Foo() {};
    	void applyTreatment( vigra::UInt16Image & image) { image.init(0);};
    };
     
     
    int	main()
    {
    	Choc choc(37984);
    	Camera_IR cam(choc, "Prisme");
     
    	Foo foo;
    	boost::function<void (Foo*, vigra::UInt16Image & )> f;
    	f = &Foo::applyTreatment;
     
     
    	cam.genererFilm(f, 0, 40, "test");
    }
    main.obj : error LNK2001: symbole externe non résolu "public: void __thiscall Camera::genererFilm<class Foo>(class boost::function<void __cdecl(class Foo *,class vigra::BasicImage<unsigned short,class std::allocator<unsigned short> > &),class std::allocator<void> >,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$genererFilm@VFoo@@@Camera@@QAEXV?$function@$$A6AXPAVFoo@@AAV?$BasicImage@GV?$allocator@G@std@@@vigra@@@ZV?$allocator@X@std@@@boost@@HHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    http://cpp.developpez.com/faq/cpp/?p...VERS_templates

    Et je pense que tu cherches beaucoup trop compliqué avec boost.function. Il te suffit de déclarer le prototype que tu souhaites manipuler (un truc qui prend un UInt16Image& et ne renvoie rien), et de lui faire correspondre ce que tu as à passer en paramètre avec boost.bind, peu importe que ce soit une fonction membre ou une fonction qui prend plus de paramètres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void Camera::genererFilm(boost::function<void (vigra::UInt16Image & )>, ...);
     
    cam.genererFilm(boost::bind(&Foo::applyTreatment, foo),...);

  4. #4
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par Boost Doc
    In many systems, callbacks often call to member functions of a particular object. This is often referred to as "argument binding", and is beyond the scope of Boost.Function. The use of member functions directly, however, is supported, so the following code is valid:
    Pourtant, c'est clairement indiqué dans la doc qu'il y a une différence!
    http://www.boost.org/doc/html/function/tutorial.html

    Dans le cas d'une structure X:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct X {
      int foo(int);
    };
    On devrait écrire avec une fonction membre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    boost::function<int (X*, int)> f;
     
    f = &X::foo;
     
    X x;

  5. #5
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par poukill Voir le message
    Pourtant, c'est clairement indiqué dans la doc qu'il y a une différence!
    http://www.boost.org/doc/html/function/tutorial.html

    Dans le cas d'une structure X:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct X {
      int foo(int);
    };
    On devrait écrire avec une fonction membre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    boost::function<int (X*, int)> f;
     
    f = &X::foo;
     
    X x;
    Ca c'est dans le cas où tu veux appeler cette fonction en fonction de l'objet et des arguments.

    Une fonction membre (pas statique) de n paramètres est en fait toujours une fonction de (n+1) paramètres, car il y a le pointeur this.

    Toi tu ne veux appeler que la fonction membre, tu t'en fous de l'objet vers qui il est appelé.

    Pour cela, il faut faire une application partielle de fonction, c'est à dire créer la même fonction en fixant un ou plusieurs paramètres, c'est ce qu'on fait avec boost::bind.

    Après, les _1, _2, _3 c'est une manière de faire des fonctions lambda en quelque sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    boost::bind(&fonction, a, _1, _2, c);
    équivaut à dire :

    soit la fonction qui à (x,y) associe fonction(a, x, y, c).

  6. #6
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    J'ai modifié mon code, j'ai maintenant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Camera::genererFilm(boost::function<void (vigra::UInt16Image & )> fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
    	boost::thread my_thread(boost::bind(&Camera::creerFilm, this,  fonct, image_debut, image_fin, nom_fichier));	
    }
    Dans le main:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int	main()
    {
    	Choc choc(37984);
    	Camera cam(choc, "Prisme");
    	Foo foo;
     
    	cam.genererFilm(boost::bind(&Foo::applyTreatment, foo), 0, 40, "test");
    }
    Ca veut pas compiler... Avec un genre d'erreur que j'ai jamais vu (cf pièce jointe)

    Comme warning :
    c:\librairies\boost_1_34_1\boost\bind.hpp(1575) : warning C4180: qualificateur appliqué au type fonction n'a pas de sens ; ignoré
    c:\librairies\boost_1_34_1\boost\bind.hpp(1609) : voir la référence à l'instanciation de la classe modèle 'boost::_bi::add_cref<Pm,I>' en cours de compilation
    with
    [
    Pm=void (__thiscall Foo::* )(vigra::UInt16Image &),
    I=1
    ]
    c:\documents and settings\gwen\bureau\prog\test\main.cpp(32) : voir la référence à l'instanciation de la classe modèle 'boost::_bi::dm_result<Pm,A1>' en cours de compilation
    with
    [
    Pm=void (__thiscall Foo::* )(vigra::UInt16Image &),
    A1=Foo
    ]
    c:\librairies\boost_1_34_1\boost\mem_fn.hpp(318) : warning C4180: qualificateur appliqué au type fonction n'a pas de sens ; ignoré
    c:\librairies\boost_1_34_1\boost\bind\bind_template.hpp(225) : voir la référence à l'instanciation de la classe modèle 'boost::_mfi::dm<R,T>' en cours de compilation
    with
    [
    R=void (vigra::UInt16Image &),
    T=Foo
    ]
    Projet : error PRJ0002 : Résultat d'erreur 1 retourné à partir de 'C:\Program Files\Microsoft Visual Studio 8\VC\bin\cl.exe'.
    Le journal de génération a été enregistré à l'emplacement "file://c:\Documents and Settings\Gwen\Bureau\prog\test\Debug\BuildLog.htm"
    test - 1 erreur(s), 2 avertissement(s)
    Là j'y comprend rien... Une idée?
    Images attachées Images attachées  

  7. #7
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Souvent dans ces cas-là j'hésite pas et je fais un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template< typename F >
    void Camera::creerFilm(F fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
      // ...
      fonc(image);
    }
    Et tout se passe bien tant qu'on donne un foncteur qui prend en argument le bon type.

    Sinon avec boost::function il faut faire quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Camera::creerFilm( boost::function1< void, vigra::UInt16Image& > fonct, int image_debut, int image_fin, std::string nom_fichier)
    {
      // ...
      fonc(image);
    }
    Et pour l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Foo foo;
    camera.creerFilm( boost::bind( &Foo::applyTreatment, foo, _1 ) );
    (si je ne me suis pas trop mélangé les pinceaux )
    (edit : ah ben si j'avais oublié 'foo' !)

    MAT.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 06/04/2011, 10h02
  2. appel à une fonction static externe
    Par marion5515 dans le forum Débuter
    Réponses: 1
    Dernier message: 09/07/2010, 11h53
  3. Réponses: 12
    Dernier message: 12/05/2006, 09h21

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