21

I have started to play around with boost python a bit and ran into a problem. I tried to expose a C++ class to python which posed no problems. But I can't seem to manage to implement the __str__ functionality for the class without getting build errors I don't understand.

I'm using boost 1_42 prebuild by boostpro. I build the library using cmake and the vs2010 compiler.

I have a very simple setup. The header-file (tutorial.h) looks like the following:

#include <iostream>
namespace TestBoostPython{
    class TestClass {
        private:
            double m_x;
        public:
            TestClass(double x);
            double Get_x() const;
            void Set_x(double x);
    };
    std::ostream &operator<<(std::ostream &ostr, const TestClass &ts);
};

and the corresponding cpp-file looks like:

#include <boost/python.hpp>
#include "tutorial.h"

using namespace TestBoostPython;

TestClass::TestClass(double x)
{
    m_x = x;
}

double TestClass::Get_x() const
{
    return m_x;
}
void TestClass::Set_x(double x)
{
    m_x = x;
}

std::ostream &operator<<(std::ostream &ostr, const TestClass &ts)
{
    ostr << ts.Get_x() << "\n";
    return ostr;
}

BOOST_PYTHON_MODULE(testme)
{
using namespace boost::python;
class_<TestClass>("TestClass", init<double>())
    .add_property("x", &TestClass::Get_x, &TestClass::Set_x)
    .def(str(self))
    ;
}

The CMakeLists.txt looks like the following:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

project (testme)

FIND_PACKAGE( Boost REQUIRED )
FIND_PACKAGE( Boost COMPONENTS python REQUIRED )
FIND_PACKAGE( PythonLibs REQUIRED )

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREAD ON)

INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
INCLUDE_DIRECTORIES ( ${PYTHON_INCLUDE_PATH} )

add_library(testme SHARED tutorial.cpp)
target_link_libraries(testme ${Boost_PYTHON_LIBRARY})
target_link_libraries(testme ${PYTHON_LIBRARY}

The build error I get is the following:

Compiling...
tutorial.cpp
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(31) : error C2780: 'void boost::python::api::object_operators::visit(ClassT &,const char *,const boost::python::detail::def_helper &) const' : expects 3 arguments - 1 provided
    with
    [
        U=boost::python::api::object
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/object_core.hpp(203) : see declaration of 'boost::python::api::object_operators::visit'
    with
    [
        U=boost::python::api::object
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(67) : see reference to function template instantiation 'void boost::python::def_visitor_access::visit,classT>(const V &,classT &)' being compiled
    with
    [
        DerivedVisitor=boost::python::api::object,
        classT=boost::python::class_,
        V=boost::python::def_visitor
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/class.hpp(225) : see reference to function template instantiation 'void boost::python::def_visitor::visit>(classT &) const' being compiled
    with
    [
        DerivedVisitor=boost::python::api::object,
        W=TestBoostPython::TestClass,
        classT=boost::python::class_
    ]
    .\tutorial.cpp(29) : see reference to function template instantiation 'boost::python::class_ &boost::python::class_::def(const boost::python::def_visitor &)' being compiled
    with
    [
        W=TestBoostPython::TestClass,
        U=boost::python::api::object,
        DerivedVisitor=boost::python::api::object
    ]

Does anyone have any idea on what went wrrong? If I remove the .def(str(self)) part from the wrapper code, everything compiles fine and the class is usable from python. I'd be very greatful for assistance.

Thank you, Rickard

edit: forgot a const

1
  • Nice! I didn't look carefully initially and defined the operator<< in the class itself rather than into the namespace like you did, which made all the difference in getting it to work to call a print(myObj) in Python. Nice work Rickard. However I noticed I still need to explicitly call print to get my object to render as I wish in python. If I just enter my object it returns results as if I called type(myObj), that may be default behavior for Python, maybe I'm getting mixed up with experience in R or Matlab though. Commented Nov 6, 2015 at 3:28

2 Answers 2

34

I recently encountered this problem; The solution that worked was to explicitly resolve the str and self on this line:

.def(str(self))

So that it becomes:

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

I don't know why this is necessary, (knowing something of the overload-resolution complication that goes on in boost python, it's probably something there...) but it worked for me :)

Sign up to request clarification or add additional context in comments.

5 Comments

Wonderful! Thanks alot. I love boost::python but when stuff goes haywire like this I think it might be easier to just hand-wrap the object in Python C-API. I would never have found this solution on my own. Thanks again.
This still worked for me today. I wonder if this should not have been fixed long time ago...?
There is a boost::python::str, and a boost::python::self_ns::str, which are very different things. This is necessary because if your code has using boost::python (as many probably will be), the compiler will find the former, which mightily confuses it.
The library isolates self_t in its own namespace, self_ns, in order to prevent the generalized operator templates which operate on it from being found by argument-dependent lookup in other contexts. This should be considered an implementation detail, since users should never have to mention self_t directly. boost.org/doc/libs/1_72_0/libs/python/doc/html/reference/…
boost::python::str is a string object while self_ns::str is a function definition. Also, they intended to have this as an implementation detail as explained above.
11

I ran into the same thing. Adding this line (instead of qualifying str and self) also works:

using self_ns::str;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.