Max Shifrin
Max Shifrin

Reputation: 809

C++ using custom smart pointers with namespace in boost python

I'm trying to exposed object in boost python, wrapped in a custom wrapped pointer.

The problem: If I put the pointer class declaration in a namespace the boost python code does not compile. If I put it outside a namespace all is well.

Example which works:

    // dummy smart MyPtr class
    template <typename T> class MyPtr {
    public:
        typedef T element_type;

        MyPtr(): px(0) {}
        MyPtr(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;
    };



template <typename T> T* get_pointer(MyPtr<T> const& p) 
{
  return const_cast<T*>(p.get());
}


namespace boost 
{ 
namespace python 
{

  template <typename T> struct pointee<MyPtr<T> >   
  {
    typedef T type;
  };
}
}

.
.
.

BOOST_PYTHON_MODULE(CmiObjectsPython)
{
.
.
bp::scope classScope = class_<NS1::Class, boost::noncopyable, MyPtr<NS1::Class> >("className", no_init)
        .def("func", &NS1::Class::func);
.
.

}

Example which does not work:

namespace NS2
{
    // dummy smart MyPtr class
    template <typename T> class MyPtr {
    public:
        typedef T element_type;

        MyPtr(): px(0) {}
        MyPtr(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;
    };
}


template <typename T> T* get_pointer(NS2::MyPtr<T> const& p) 
{
  return const_cast<T*>(p.get());
}


namespace boost 
{ 
namespace python 
{

  template <typename T> struct pointee<NS2::MyPtr<T> >   
  {
    typedef T type;
  };
}
}

.
.
.

BOOST_PYTHON_MODULE(CmiObjectsPython)
{
.
.
bp::scope classScope = class_<NS1::Class, boost::noncopyable, NS2::MyPtr<NS1::Class> >("className", no_init)
        .def("func", &NS1::Class::func);
.
.

}

If I add:

using namespace NS2;

This has no effect.

The errors I get surround the inexistence of get_pointer for the class: /usr/include/boost/python/object/make_ptr_instance.hpp:30: error: no matching function for call to 'get_pointer(const NS2::MyPtr&)' (template error redacted for readability - obviously there are 20 lines of trails until this line is achieved.

The boost code in the make_ptr_instance looks like:

template <class Ptr>
static inline PyTypeObject* get_class_object(Ptr const& x)
{
    return get_class_object_impl(get_pointer(x));
}

So there is no real reason for the code not to work as far as I understand, since get_pointer is defined, and is outside a namespace as boost python expects.

What am I missing here?

Thanks, Max.

Upvotes: 1

Views: 487

Answers (1)

kvorobiev
kvorobiev

Reputation: 5070

Unfortunately, many features of boost python are poorly documented. As I see from your code you need to move

template <typename T> T* get_pointer(NS2::MyPtr<T> const& p) 
{
  return const_cast<T*>(p.get());
}

into the same namespace, that contains MyPtr definition. Something like this

namespace NS2 
{
    template <typename T> T* get_pointer(MyPtr<T> const& p) 
    {
        return const_cast<T*>(p.get());
    }
}

Upvotes: 3

Related Questions