There are two errors in the initial code:
- Boost.Python is attempting to pass two arguments (
self
and an instance ofFoo
) to the staticWine::do_something()
C++ function that only accepts one argument. To resolve this, when exposing theWine
class, the PythonWine.do_something()
member function needs to be set as static via theboost::python::class_::staticmethod()
member function. When exposed as a static method, Boost.Python will no longer pass theself
instance argument. - Unlike the Python/C API, where pointers are often used as handles to objects (
PyObject*
), Boost.Python provides a higher-level notationboost::python::object
class that is often passed around by value or reference. Internally, this class interacts with aboost::python::handle
that performs smart pointer management forPyObject
.
Here is a complete Python extension based on the original code:
#include <boost/python.hpp>
class Wine
{
public:
static void do_something(boost::python::object object)
{
int a = 1;
int b = 2;
int c = 3;
object.attr("Bar1")(a, b, c);
object.attr("Bar2")(a, b, c);
};
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<Wine>("Wine")
.def("do_something", &Wine::do_something)
.staticmethod("do_something")
;
};
Interactive usage:
>>> class Foo(object):
... def Bar1(self, a, b, c):
... print "Bar1", locals()
... def Bar2(self, a, b, c):
... print "Bar2", locals()
...
>>> import example
>>> cheese = example.Wine()
>>> cheese.do_something(Foo())
Bar1 {'a': 1, 'c': 3, 'b': 2, 'self': <__main__.Foo object at 0xb6b0f2ac>}
Bar2 {'a': 1, 'c': 3, 'b': 2, 'self': <__main__.Foo object at 0xb6b0f2ac>}