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 :

[Python] Appeller une fonction membre redéfinie depuis C++


Sujet :

Boost C++

  1. #1
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut [Python] Appeller une fonction membre redéfinie depuis C++
    Yop !

    Voici mon code C++:

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    namespace bp = boost::python;
     
    struct Base {
    	virtual void process() {}
    };
     
    struct BaseWrapper: public Base, bp::wrapper< Base > {
    	BaseWrapper( Base const & b ) :
    		Base( b ),
    		bp::wrapper< Base >() {}
     
    	BaseWrapper() :
    		Base(),
    		bp::wrapper< Base >() {}
     
    	virtual void process() {
    		if( bp::override fct = this->get_override( "process" ) ) {
    			fct();
    		} else {
    			Base::process();
    		}
    	}
    };
     
    BOOST_PYTHON_MODULE( MyModule )
    {
    	bp::class_< BaseWrapper >( "Base" )
    	  .def( "process", &Base::process );
    }
     
    int main( int argc, char ** argv ) {
    	try {
    		PyImport_AppendInittab( (char*)"MyModule", &initMyModule );
    		Py_Initialize();
     
    		bp::object main_module = bp::import("__main__");
    		bp::object MyModule = bp::import("MyModule");
     
    		bp::object main_namespace = main_module.attr("__dict__");
    		main_namespace["MyModule"] = MyModule;
     
    		bp::object result = bp::exec_file( "script.py", main_namespace );
     
    	} catch( bp::error_already_set const& ) {
    		PyErr_Print();
    	}
    }
    Et voici mon code python:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    import MyModule;
     
    class Derived( MyModule.Base ):
      def process():
        print 'Processing';
    Je vois pas comment faire en sorte que le programme C++ affiche 'Processing' en appellant Derived.process(). J'ai tenté d'extract dans tous les sens, rien à faire. Du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    bp::object derived = bp::extract< bp::object >( main_namespace["Derived"] );	
    // je ne vois pas comment je peux instancier la classe et l'upcast en Base* ici
    Si j'essai de lancer directement une fonction membre j'obtiens (logiquement):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    derived.attr("process")();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TypeError: unbound method process() must be called with Derived instance as first argument (got nothing instead)
    Merci d'avance !

  2. #2
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Bon, j'ai réussi.

    Voici mon code C++:

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <boost/python.hpp>
    #include <iostream>
    #include <memory>
     
    namespace bp = boost::python;
     
    struct Base {
    	virtual void process() {
    		std::cout << "base" << std::endl;
    	}
    	virtual ~Base() {}
    };
     
    bp::object obj;
     
    struct BaseWrapper: public Base, bp::wrapper< Base > {
    	BaseWrapper( PyObject* self_, Base const & b ) :
    		self( self_ ),
    		Base( b ),
    		bp::wrapper< Base >( ) {
    			Py_INCREF( self );
    	}
     
    	BaseWrapper(PyObject* self_) :
    	    self( self_ ),
    		Base(),
    		bp::wrapper< Base >() {
    			Py_INCREF( self );
    			std::cout << "created!" << std::endl;
    	}
     
    	virtual void process() {
    		if( bp::override fct = this->get_override( "process" ) ) {
    			fct();
    		} else {
    			Base::process();
    		}
    	}
     
    	virtual ~BaseWrapper() {
    		std::cout << "destroyed!" << std::endl;
    		Py_DECREF(self);
    	}
     
    	PyObject* self;
    };
     
    void registerObject( bp::object o )
    {
    	obj = o;
    }
     
    BOOST_PYTHON_MODULE( MyModule )
    {
    	bp::class_< Base, std::auto_ptr< BaseWrapper > >( "Base" )
    	  .def( "process", &Base::process );
     
    	def( "registerObject", registerObject );
    }
     
    int main( int argc, char ** argv ) {
    	try {
    		PyImport_AppendInittab( (char*)"MyModule", &initMyModule );
    		Py_Initialize();
     
    		bp::object main_module = bp::import("__main__");
    		bp::object MyModule = bp::import("MyModule");
     
    		bp::object main_namespace = main_module.attr("__dict__");
    		main_namespace["MyModule"] = MyModule;
     
    		bp::object result = bp::exec_file( "embedded.py", main_namespace );	
    	} catch( bp::error_already_set const& ) {
    		PyErr_Print();
    	}
     
    	obj.attr("process")();
    }
    Et mon embedded.py:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import MyModule;
     
    class Derived( MyModule.Base ):
      def process(self):
        print 'Processing';
     
    MyModule.registerObject( Derived() );
    C'était pas de tout repos, vu la qualité de la doc, c'était à coup de trial & fail...

    Du coup, si quelqu'un a des conseils, je suis preneur car je sais pas du tout si c'est la bonne méthode... Bien sûr je compte associer ça à une Factory qui s'occupe du register pour garder trace des objets, ici c'était juste pour l'exemple .

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

Discussions similaires

  1. [Débutant] Appeler une fonction du CodeBehind depuis un webform avec page maître
    Par ptichub dans le forum ASP.NET
    Réponses: 2
    Dernier message: 22/08/2013, 16h55
  2. [Débutant] Appeler une fonction du CodeBehind depuis un webform avec page maître
    Par ptichub dans le forum VB.NET
    Réponses: 2
    Dernier message: 22/08/2013, 16h55
  3. [Débutant] Appeler une fonction du CodeBehind depuis le Aspx
    Par ptichub dans le forum VB.NET
    Réponses: 2
    Dernier message: 22/08/2013, 10h50
  4. [Débutant] Appeler une fonction DLL C# depuis le C++ par API LOADLIBRARY
    Par yann458 dans le forum C#
    Réponses: 3
    Dernier message: 07/05/2013, 23h49
  5. un programme en python appelle une fonction C .. ?
    Par ikuzar dans le forum Débuter
    Réponses: 2
    Dernier message: 02/09/2010, 10h58

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