[C++-sig] Conversion of python files to C++ ostreams

Christopher Bruns cmbruns at stanford.edu
Tue Apr 6 17:52:40 CEST 2010


On Sun, Apr 4, 2010 at 1:07 PM, Christopher Bruns <cmbruns at stanford.edu> wrote:
[...]
>>> // C++ API
>>> struct Foo {
>>>     Foo(ostream& os);
>>> };
>>>
>>> # desired python usage
>>> foo = Foo(streambuf(sys.stdout))

Solved. Thanks everyone was politely waiting for me to find the answer
in the FAQ at http://wiki.python.org/moin/boost.python/HowTo#namedconstructors.2BAC8factories.28asPythoninitializers.29

The way to wrap constructors such as this is like so:

////////////
        namespace bp = boost::python;
        // I am still debating whether to use streambuf or FileObj, so
both approaches shown...
        using boost_adaptbx::python::streambuf;
        using mds_utils::python::oFileObj;
        // Create wrapper methods for the desired constructors
        static boost::shared_ptr<Foo> makeFoo1(streambuf& output) {
            streambuf::ostream os(output);
            return boost::shared_ptr<Foo>(new Foo(os));
        }
        static boost::shared_ptr<Foo> makeFoo2(oFileObj& output) {
            std::ostream& os = static_cast<std::ostream&>(output);
            return boost::shared_ptr<Foo>(new Foo(os));
        }
        // This one must be treated carefully, since it can take any
boost::python object as an argument
        static boost::shared_ptr<Foo> makeFoo3(bp::object& pyfile) {
            // oFileObj output(pyfile);
            // return makeFoo2(output);
            // or
            streambuf output(pyfile);
            return makeFoo1(output);
        }
        [...]
BOOST_PYTHON_MODULE(_test) {
    bp::class_< Foo >("Foo", bp::init<>())
        // First method declared here is last method to be consulted
during overload resolution
        .def("__init__", bp::make_constructor(makeFoo3)) // This one
MUST be defined first!
        .def(bp::init< std::ostream& >())
        .def("__init__", bp::make_constructor(makeFoo1))
        .def("__init__", bp::make_constructor(makeFoo2))
        ;
}
////////////

Now in python I can use any of the following:

foo = Foo(test_.cout) # actual C++ ostream
foo = Foo(streambuf(sys.stdout)) # boost_adaptbx wrapper
foo = Foo(oFileObje(sys.stdout)) # mds_utils wrapper
foo = Foo(sys.stdout) # seamless file object conversion, what I wanted
all along.


More information about the Cplusplus-sig mailing list