#include <osg/ref_ptr>
#include <osg/Referenced>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/wrapper.hpp>
#include <iostream>
using namespace boost::python;
/**
* Contrived model of the 3rd-party lib
*/
class VisitorBase : public osg::Referenced {
public:
virtual const char* name(){ return "VisitorBase"; }
protected :
virtual ~VisitorBase(){};
};
class DerivedVisitor : public VisitorBase {
public:
virtual const char* name(){ return "DerivedVisitor"; }
protected :
virtual ~DerivedVisitor(){};
};
class HelperVisitor : public VisitorBase {
public:
virtual const char* name(){ return "HelperVisitor"; }
protected :
virtual ~HelperVisitor(){};
};
class Node {
public:
virtual void apply( VisitorBase& b ){
std::cerr<<" ( C++ ) Hi my name is "<< b.name() << std::endl ;
}
};
void check_their_identification( Node& n, VisitorBase& b){
n.apply( b );
osg::ref_ptr<HelperVisitor> helper = osg::ref_ptr<HelperVisitor>( new HelperVisitor );
n.apply( *helper );
}
/**
* This is where the pybindings start
*/
namespace boost {
namespace python {
template <class T> struct pointee< osg::ref_ptr<T> >
{
typedef T type;
};
}
}
struct VisitorBase_wrapper : VisitorBase, wrapper<VisitorBase> {
VisitorBase_wrapper( PyObject* o ) : self( o ), VisitorBase() {};
VisitorBase_wrapper( PyObject* o , const VisitorBase& b) : self( o ), VisitorBase(b) {};
const char* name(){
if( override name = this->get_override("name") ) return name();
else return VisitorBase::name();
}
const char* default_name(){ return this->VisitorBase::name(); }
private:
PyObject* self;
};
struct Node_wrapper : Node, wrapper<Node> {
void apply( VisitorBase& b ){
if( override apply = this->get_override("apply") ) {
// This slices all objects to VisitorBase
apply( b );
// This fails for objects that are not wrapped
//apply( boost::ref(b) );
}
else Node::apply( b );
}
void default_apply( VisitorBase& b ){ this->Node::apply( b ); }
};
BOOST_PYTHON_MODULE(boost_python_and_ref_ptr)
{
class_<osg::Referenced, osg::ref_ptr<osg::Referenced> >("Referenced");
// the order here is important
// VisitorBase_wrapper *must* come before ref_ptr<VisitorBase>
class_<VisitorBase, bases<osg::Referenced>, VisitorBase_wrapper, osg::ref_ptr<VisitorBase> >("VisitorBase")
.add_property("name", &VisitorBase_wrapper::default_name)
;
class_<DerivedVisitor, bases<VisitorBase>, osg::ref_ptr<DerivedVisitor> >("DerivedVisitor")
.add_property("name", &DerivedVisitor::name)
;
class_<Node_wrapper, boost::noncopyable>("Node")
.def("apply", &Node::apply, &Node_wrapper::default_apply)
;
def("check_their_identification", &check_their_identification );
}