Search code examples
python-2.7boost-pythonostream

Boost.Python: Unable to wrap C++ "operator<<" to expose print functionality in Python


I am trying to wrap a C++ class that handles binary values using Boost.Python. For this class, the "<<" operator has been defined as

std::ostream &operator<<(std::ostream &output, const bin &inbin);

I tried wrapping it with

class_<bin>("bin", init<>())
    .def(str(self));

However, the compilation throws this error:

boost/python/def_visitor.hpp:31:9: error: no matching function for call to
‘boost::python::api::object::visit(boost::python::class_<itpp::bin>&) const’

I am not sure how to resolve this error, anyone have an idea?

Reference: http://www.boost.org/doc/libs/1_31_0/libs/python/doc/tutorial/doc/class_operators_special_functions.html


Solution

  • This somehow seems to be covered in the following SO posts:
    what is wrong with c++ streams when using boost.python?
    Build problems when adding `__str__` method to Boost Python C++ class

    So, according to the previous posts, you should try to substitute

    .def(str(self));  
    

    with either

    .def(self_ns::str(self)); 
    

    or

    .def(self_ns::str(self_ns::self))  
    

    It seems to have resolved the same problem in those cases.

    If the above doesn't work, try writing a custom wrapper. For example, you may define a print_wrap function as:

    #include <sstream>
    std::string print_wrap(const classname &c)
    {
      std::ostringstream oss;
      oss << "HelloWorld " << c.var1 << " " << c.var2;
      return oss.str();
    }
    

    And then in the class_<classname>("py_classname") definition use,

    .def("__str__", &print_wrap)
    

    Then in Python you should be able to get

    >>> obj = py_classname(1,2)  #var1=1, var2=2
    >>> print obj
    >>> HelloWorld 1 2