#include <boost/python.hpp>
#include <iostream>

using namespace boost::python;
using namespace std;

class Base {
public:
  Base() : m_first(0) {
    cout << "Base constructor 0, m_first: "
      << m_first << endl;
  }
  Base(int first) : m_first(first) {
    cout << "Base constructor 1, m_first: " 
      << m_first << endl;
  }
  ~Base(){}
  virtual void print(){
    cout << "This is Base." << endl;
  }
  int get_first() const{return m_first;}
  void set_first(int num){m_first = num;}
protected:
  int m_first;
};

class Derived : public Base{
public:
  Derived() : Base(), m_second(0) {}
  Derived(int second) : Base(), m_second(second) {}
  Derived(int first, int second) : Base(first), m_second(second) {}
  ~Derived(){}
  void print(){
    cout << "This is Derived (" << m_first << ", " << m_second << ")." << endl;
  }
  int get_second() const {return m_second;}
  void set_second(int num) {m_second = num;}
protected:
  int m_second;
};

class PrueVirtualClass {
public:
  PrueVirtualClass(){}
  virtual ~PrueVirtualClass () = default;
  virtual int f() = 0;
};

struct PrueVirtualClassWrap : PrueVirtualClass, wrapper<PrueVirtualClass> {
  PrueVirtualClassWrap(): PrueVirtualClass(){}
  int f() {
    return this->get_override("f")();
  }
};

BOOST_PYTHON_MODULE(_class_example) {
  class_<Base>("Base")
    .def(init<int>())
    .def("print", &Base::print)
    .add_property("m_first", &Base::get_first) //, &Base::set_first)
  ;

  // class_<Derived, bases<Base> >("Derived")
  class_<Derived >("Derived")
    .def(init<int>())
    .def(init<int, int>())
    .def("print", &Derived::print)
    .add_property("m_second", &Derived::get_second, &Derived::set_second)
  ;

  class_<PrueVirtualClassWrap, boost::noncopyable>("prueVirtualClass", init<>())
    .def("f", pure_virtual(&PrueVirtualClass::f))
  ;
}
