Oh, I assumed that boost::python::object did this already.
It does. Think of bp::handle<> as a low-level, bare-bones, smart PyObject*. Think of bp::object as that, *plus* all the fancy c++ API that maps to python API (like obj.attr("foo"), []-operator, ()-operator, etc). I believe bp::object holds a handle<> internally.
If not, is there any reason not to use boost::python::handle<boost::python::object> everywhere instead of a boost::python::object?
Don't do that. You can't do that. It won't compile. Use bp::object everywhere unless you're convinced you have a good reason to do otherwise. If you have a PyObject *p and you want a bp::object, construct it via: object(handle<>(p)) // when p's a new reference object(handle<>(borrowed(p))) // when p's a borrowed reference
One of my main reasons for using boost::python instead of the C API is to avoid worrying so much about the reference counting. For instance, I don't want to explicitly increment the ref when returning a PyObject, or remember whether I should take a ref when given a PyObject from various functions.
Yup. Just use bp::object everywhere. I recommend you read through the reference manual: http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/object.html http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/handle.html Also look at the tutorials and examples and tests in the boost.python distribution. Alex