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

Christopher Bruns cmbruns at stanford.edu
Sun Apr 4 22:07:11 CEST 2010


On Sat, Apr 3, 2010 at 8:54 PM, Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> wrote:
>> // C++ API
>> struct Foo {
>>     Foo(ostream& os);
>> };
>>
>> # desired python usage
>> foo = Foo(streambuf(sys.stdout))
>
> Did you already try the usual
>
>  def(init<ostream&>((arg("os"))))

Yes.  Well pretty close.  Py++ code generator gives me this:

    Foo_exposer.def( bp::init< std::ostream & >(( bp::arg("os") )) );

which I believe is completely equivalent.  Given the following test API:

///// C++ API to wrap ////
#include <iostream>
class Foo {
public:
    Foo() {std::cout << "constructor1" << std::endl;}
    // The following constructor that takes an ostream& is the tricky part
    explicit Foo(std::ostream& os) {os << "constructor2" << std::endl;}
    // These say_hello member functions can be wrapped using current technology
    void say_hello_fileobj(std::ostream& os) {os << "hello fileobj" <<
std::endl;}
    void say_hello_streambuf(std::ostream& os) {os << "hello
streambuf" << std::endl;}
};
////////////////////////

I can wrap the say_hello_streambuf() member function with wrapper
functions like these:

        namespace bp = boost::python;
        using boost_adaptbx::python::streambuf;
        void foo_say_hello_streambuf_wrapper1(Foo& foo, streambuf& output) {
            streambuf::ostream os(output);
            foo.say_hello_streambuf(os);
        }
        void foo_say_hello_streambuf_wrapper2(Foo& foo, bp::object& pyfile) {
            streambuf output(pyfile);
            foo_say_hello_streambuf_wrapper1(foo, output);
        }
[...]
BOOST_PYTHON_MODULE('_test') {
    [...]
    bp::class_< Foo >("Foo", bp::init< >())
        .def( bp::init< std::ostream & >(( bp::arg("os") ))
        .def("say_hello_streambuf", &foo_say_hello_streambuf_wrapper2)
        .def("say_hello_streambuf", &Foo::say_hello_streambuf)
        .def("say_hello_streambuf", &foo_say_hello_streambuf_wrapper1)
        [...]
}

I know how to create wrapper methods to delegate the member_functions,
but I don't know how to create a wrapper method for the constructor.

###### python test program ######
import _test as test
import sys

foo = test.Foo()

# Test ostream wrapping based on Ralf W. Grosse-Kunstleve's
# boost_adaptbx::python::streambuf class
foo.say_hello_streambuf(test.cout) # OK
foo.say_hello_streambuf(test.streambuf(sys.stdout)) # OK
foo.say_hello_streambuf(sys.stdout) # OK

# Test wrapping based on Michele De Stefano's
# mds_utils::python::oFileObj class
foo.say_hello_fileobj(test.cout) # OK
foo.say_hello_fileobj(test.oFileObj(sys.stdout)) # OK
foo.say_hello_fileobj(sys.stdout) # OK

# But I don't know how to create a wrapper to delegate this constructor
for ctor_arg in (
            test.cout, # OK
            test.streambuf(sys.stdout), # Boost.Python.ArgumentError
            test.oFileObj(sys.stdout), # Boost.Python.ArgumentError
            sys.stdout # Boost.Python.ArgumentError
            ):
    try:
        foo = test.Foo(ctor_arg)
    except ArgumentError:
        print "Argument error with argument %s" % ctor_arg
#####################

desired output of test program:
=====================
constructor1
hello streambuf
hello streambuf
hello streambuf
hello fileobj
hello fileobj
hello fileobj
constructor2
constructor2
constructor2
constructor2

actual output of test program:
=====================
constructor1
hello streambuf
hello streambuf
hello streambuf
hello fileobj
hello fileobj
hello fileobj
constructor2
Argument error with argument <_test.streambuf object at 0x00B75DB0>
Argument error with argument <_test.oFileObj object at 0x00B75E40>
Argument error with argument <open file '<stdout>', mode 'w' at 0x00373070>


More information about the Cplusplus-sig mailing list