|
Boost.PythonHeader <boost/python/errors.hpp> |
error_already_set
error_already_set
synopsis
<boost/python/errors.hpp>
provides types and
functions for managing and translating between Python and C++ exceptions.
This is relatively low-level functionality that is mostly used internally
by Boost.Python. Users should seldom need it.
error_already_set
error_already_set
is an exception type which can be thrown
to indicate that a Python error has occurred. If thrown, the precondition
is that PyErr_Occurred()
returns a value convertible to true
.
namespace boost { namespace python { class error_already_set {}; }}
template <class T> bool handle_exception(T f) throw(); void handle_exception() throw();
function0<void>(f)
is valid. The second form requires that a C++ exception is currently
being handled (see section 15.1 in the C++ standard).
f()
inside a
try
block whose catch
clauses set an
appropriate Python exception for the C++ exception caught, returning
true
if an exception was caught, false
otherwise. The second form passes a function which rethrows the exception
currently being handled to the first form.
handle_exception
to manage exception translation whenever
your C++ code is called directly from the Python API. This is done for
you automatically by the usual function wrapping facilities: make_function(), make_constructor(), module::def and class_::def). The second form can be more
convenient to use (see the example below), but
various compilers have problems when exceptions are rethrown from within
an enclosing try
block.
PyObject* expect_non_null(PyObject* x); template <class T> T* expect_non_null(T* x);
x
error_already_set()
iff x ==
0
.
#include <string> #include <boost/python/errors.hpp> #include <boost/python/reference.hpp> // Returns a std::string which has the same value as obj's "__name__" // attribute. std::string get_name(boost::python::ref obj) { // throws if there's no __name__ attribute PyObject* p = boost::python::expect_non_null( PyObject_GetAttrString(obj.get(), "__name__")); // throws if it's not a Python string std::string result( boost::python::expect_non_null( PyString_AsString(p))); Py_XDECREF(p); // Done with p return result; } // // Demonstrate form 1 of handle_exception // // Place a Python Int object whose value is 1 if a and b have // identical "__name__" attributes, 0 otherwise. void same_name_impl(PyObject*& result, PyObject* a, PyObject* b) { result = PyInt_FromLong( get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2))); } // This is an example Python 'C' API interface function extern "C" PyObject* same_name(PyObject* args, PyObject* keywords) { PyObject* a1; PyObject* a2; PyObject* result = 0; if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2)) return 0; // Use boost::bind to make an object compatible with // boost::Function0<void> if (boost::python::handle_exception( boost::bind<void>(same_name_impl, boost::ref(result), a1, a2))) { // an exception was thrown; the Python error was set by // handle_exception() return 0; } return result; } // // Demonstrate form 2 of handle_exception. Not well-supported by all // compilers. // extern "C" PyObject* same_name2(PyObject* args, PyObject* keywords) { PyObject* a1; PyObject* a2; PyObject* result = 0; if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2)) return 0; try { return PyInt_FromLong( get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2))); } catch(...) { // If an exception was thrown, translate it to Python boost::python::handle_exception(); return 0; } }
Revised 05 November, 2001
© Copyright Dave Abrahams 2002. All Rights Reserved.