I have an example C++ base class (Song) with a virtual method (chorus) 
returning void that is called by another method (play) of the same class.  I 
want to be able to derive a python class from this and override the virtual 
method.  I experience the following behavior:

1. If I simply instantiate the wrapped base class in python and call play, 
**the virtual chorus is never entered/executed**.
2. If I create a derived class and override the virtual chorus, the derived 
chorus is executed correctly.
3. If I change the base class chorus to return int (or anything) instead of 
void, the base class chorus is executed correctly.

I have wrapped my class as described here: 
http://www.boost.org/doc/libs/1_43_0/libs/python/doc/v2/wrapper.html

My example C++,  python code, and output python output is below (I've tried to 
make it as concise as possible).  I can work around this issue in my 
application by having my virtual method return an unused object, although this 
is not ideal.  I would appreciate any other suggestions, whether I'm doing 
something incorrectly, or is this possibly a boost python bug?

//------------------------------------------------
//  Has virtual method returning void
//  Numbers indicate order in which the print statements should appear.
//------------------------------------------------
class Song
{
public:
    virtual ~Song(){}
    void play()
    {
        std::cout << "\n1) Base class --> Song.play" << std::endl;
        chorus();
        std::cout << "3) Base class <-- Song.play" << std::endl;
    }

    // THIS METHOD IS NEVER EXECUTED
    virtual void chorus()
    {
        std::cout << "2) Base class Song.chorus returning void" << std::endl;
    }
};

struct SongWrapper :  Song, bp::wrapper<Song>
{
    void chorus()
    {
        if (bp::override chorus = this->get_override("chorus"))
                chorus();
                return;
        Song::chorus();
        return;
    }

    void default_chorus()    {  this->Song::chorus(); }
};

//------------------------------------------------
//  Has virtual method returning int
//  Numbers indicate order in which the print statements should appear.
//------------------------------------------------
class AnotherSong
{
public:
    virtual ~AnotherSong(){}
    void play()
    {
        std::cout << "\n1) Base class --> AnotherSong.play" << std::endl;
        chorus();
        std::cout << "3) Base class <--AnotherSong.play" << std::endl;
    }

   // THIS METHOD (returning int) IS EXECUTED
    virtual int chorus()
    {
        std::cout << "2) Base class AnotherSong.chorus returning int" << 
std::endl;
        return 0;
    }
};

struct AnotherSongWrapper :  AnotherSong, bp::wrapper<AnotherSong>
{
    int chorus()
    {
        if (bp::override chorus = this->get_override("chorus"))
                return chorus();
        return AnotherSong::chorus();
    }

    int default_chorus()   {  return this->AnotherSong::chorus(); }
};

BOOST_PYTHON_MODULE(Songs)
{
    bp::class_<SongWrapper,boost::noncopyable>("Song")
       .def("play", &Song::play)
       .def("chorus", &Song::chorus, &SongWrapper::default_chorus)
       ;

    bp::class_<AnotherSongWrapper,boost::noncopyable>("AnotherSong")
       .def("play", &AnotherSong::play)
       .def("chorus", &AnotherSong::chorus, &AnotherSongWrapper::default_chorus)
       ;
}
#------------------------------------------------
# Python file ...
#------------------------------------------------
from Songs import Song, AnotherSong

# Base class chorus returning void is not executed: step 2 is missing in the 
output
s1 = Song()
s1.play()

# Derived class chorus is executed: step 2 in the output
class Chart(Song):
    def chorus(self):
        print "** 2) Derived class Chart.chorus"
c1 = Chart()
c1.play()

# Base class chorus returning int is executed: step 2 in output
s2 = AnotherSong()
s2.play()

#------------------------------------------------
# Python output ...
# In first case, step 2 is missing ... chorus was not executed
#------------------------------------------------
1) Base class --> Song.play
3) Base class <-- Song.play

1) Base class --> Song.play
** 2) Derived class Chart.chorus
3) Base class <-- Song.play

1) Base class --> AnotherSong.play
2) Base class AnotherSong.chorus returning int
3) Base class <--AnotherSong.play


________________________________

This email is intended solely for the recipient. It may contain privileged, 
proprietary or confidential information or material. If you are not the 
intended recipient, please delete this email and any attachments and notify the 
sender of the error.
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
https://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to