I would like to expose objects wrapped in custom smart pointers in python using Boost::Python
The caveats
The problem is that I cannot seem to get it quite right. Here's a sample code:
LegacyCode::Ptr -> legacy smart pointer code
LegacyCode::Session -> legacy object that's wrapped in the legacy smart pointer
namespace boost { namespace python
{
    template <class T> T* get_pointer(LegacyCode::Ptr<T> const& p)
    {
        return p.get();
    }
    template <typename T>
    struct pointee<LegacyCode::Ptr<T> >
    {
        typedef T type;
    };
}}*
BOOST_PYTHON_MODULE(pyro)
{
    using namespace boost::python;
    class_<LegacyCode::Session,LegacyCode::Ptr<LegacyCode::Session>>("Session")
                                          .def("get_type",&LegacyCode::Session::getType);
}
                Here is a fully working example. You almost had it - you have to remove the get_pointer() from the boost::python namespace.
#include <boost/python.hpp>
// dummy smart ptr class
template <typename T> class Ptr {
  public:
    typedef T element_type;
    Ptr(): px(0) {}
    Ptr(T* p): px(p) {}
    // base operators
    T* operator->() { return px; }
    const T* operator->() const { return px; }
    T& operator*() { return *px; }
    const T& operator*() const { return *px; }
    // getters
    T* get() { return px; }
    const T* get() const { return px; }
  private:
    T* px;
};
// a dummy class that will be held by your custom smart pointer
class  Session {
  public:
    Session(int value) : value_(value) {}
    virtual ~Session() {}
    // a few methods to play with the class
    int value() const { return value_; };
    void value(int value) { value_ = value; }
  private:
    int value_;
};
// this emulates methods actually using your smart pointers
void print_value_1(const Ptr<Session>& s) {
  std::cout << "[by const reference] The value of this session is " << s->value() << std::endl;
}
void print_value_2(Ptr<Session> s) {
  std::cout << "[by value] The value of this session is " << s->value() << std::endl;
}
// here comes the magic
template <typename T> T* get_pointer(Ptr<T> const& p) {
  //notice the const_cast<> at this point
  //for some unknown reason, bp likes to have it like that
  return const_cast<T*>(p.get());
}
// some boost.python plumbing is required as you already know
namespace boost { namespace python {
  template <typename T> struct pointee<Ptr<T> > {
    typedef T type;
  };
} }
// now the module
BOOST_PYTHON_MODULE(example) {
  using namespace boost::python;
  class_<Session, Ptr<Session>, boost::noncopyable>("Session", init<int>());
  def("print_value_1", &print_value_1);
  def("print_value_2", &print_value_2);
}
You can test this with the following python code:
import example
s = example.Session(27)
example.print_value_1(s)
example.print_value_2(s)
We demonstrate with the example that boost.python will correctly run the conversion as required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With