Boost logo

Boost :

Subject: [boost] boost::python feature request: unique_ptr, interfaces and factory functions
From: Maxim Yegorushkin (maxim.yegorushkin_at_[hidden])
Date: 2012-10-20 10:43:08


Hi Boost,

I am using boost::python to expose a C++ API into Python. The class I
would like to export is:

    struct Subscriber {
        virtual ~Subscriber() = 0;
        static std::unique_ptr<Subscriber> create();
    };

It's an interface with a factory function returning a std::unique_ptr<>.
I would like to be able to export it in the following manner:

     BOOST_PYTHON_MODULE(pub_sub) {
         boost::python::class_<
               Subscriber
             , std::unique_ptr<Subscriber>
             , boost::noncopyable
>("Subscriber")
             .def(boost::python::init<>, Subscriber::create)
             ;
         ;
     }

I.e., the python wrapper would hold a std::unique_ptr<Subscriber> and
use Subscriber::create() factory function as a constructor for Python
Subscriber class.

The above code doesn't compile with boost-1.51.0 for two reasons:

     * std::unique_ptr<> is not supported by boost::python. On the other
hand, std::auto_ptr<> is.
     * The factory function can't be used used as a Python object
constructor.

I thought there could be a way to specialize certain boost::python
traits/metaclasses to make it work with std::unique_ptr<> and factory
functions as constructors, but couldn't figure it out.

The workaround I managed to get working is:

     std::auto_ptr<Subscriber> createSubscriber() {
         return std::auto_ptr<Subscriber>(Subscriber::create().release());
     }

     BOOST_PYTHON_MODULE(pub_sub) {
         // Expose the class.
         boost::python::class_<
               Subscriber
             , std::auto_ptr<Subscriber>
             , boost::noncopyable
>("Subscriber_", boost::python::no_init)
             ;
         ;

         // Expose its factory function.
         boost::python::def("Subscriber", createSubscriber);
     }

I.e., std::unique_ptr<> gets replaced with std::auto_ptr<>, the Python
class is renamed to Subscriber_ and the factory function gets exported
as Subscriber allowing for Python syntax:

     import pub_sub
     s = pub_sub.Subscriber()

     # however
     assert isinstance(s, pub_sub.Subscriber) # fails
     assert isinstance(s, pub_sub.Subscriber_) # succeeds

So, I was wondering if there are ways to make my original Python class
export syntax work?

-- Maxim


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk