boost python operator overloading for calling C++ classes

3. July 2012 08:00

 

In a previous post about creating basic python wrappers. I mentioned that there can be an issue with trying to call C++ from the python wrapper which are operator overloaded. Taking the following C++ code the python wrapper cannot tell the different between the two functions when being compile or which one should be used.

 

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
		
		std::string Example(std::string str) {
			return str;
		}
};

BOOST_PYTHON_MODULE(MyClass_py)
{

	class_( "MyClass", init<>() )
	
		.def("Example", &MyClass::Example)
		
	;
	
}

When compiling you will get en error of this.

 

MyClass_py.cpp: In function 'void init_module_MyClass_py()':
MyClass_py.cpp:44: error: no matching function for call to 'boost::python::class_<MyClass, boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::def(const char [8], <unresolved overloaded function type>)'

 

You can work around it using the static cast to get the correct function to be called and rename the python function to something else. Effectivly this removes the operating overload from the python end of things when it is not supported. The example of the wrapper code is below.

 

BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		.def("ExampleStr", static_cast< std::string (MyClass::*)(std::string ) > (&MyClass::Example) )
		
	;
	
}

Our python code is then forced to use the aliased function name.

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
'Hello World'
>>> obj.ExampleStr('Foo')
'Foo'
>>>

I have included an complete example for you to play with.

 

#include <string>

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

using namespace boost::python;

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
		
		std::string Example(std::string str) {
			return str;
		}
};


BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		.def("ExampleStr", static_cast< std::string (MyClass::*)(std::string ) > (&MyClass::Example) )
		
	;
	
}

 

You can compile the above with

 

g++ -shared -Wall MyClass_py.cpp -o MyClass_py.so -I/usr/include/python2.6/ -lboost_python -lpython2.6

E-mail Kick it! DZone it! del.icio.us Permalink