|
|
Boost.PythonHeader <boost/python/errors.hpp> |
error_already_seterror_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_seterror_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. Portable code shouldn't
throw this exception type directly, but should instead use throw_error_already_set(),
below.
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 which first attempts to use all registered exception translators. If none of
those translates the exception, the catch clauses then set
an appropriate Python exception for the C++ exception caught, returning
true if an exception was thrown, 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(),
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.template <class T> T* expect_non_null(T* x);
xerror_already_set() iff x ==
0.void throw_error_already_set();
throw error_already_set();catch block in handle_exception() can catch the
exception.
#include <string>
#include <boost/python/errors.hpp>
#include <boost/python/object.hpp>
#include <boost/python/handle.hpp>
// Returns a std::string which has the same value as obj's "__name__"
// attribute.
std::string get_name(boost::python::object obj)
{
// throws if there's no __name__ attribute
PyObject* p = boost::python::expect_non_null(
PyObject_GetAttrString(obj.ptr(), "__name__"));
char const* s = PyString_AsString(p);
if (s != 0)
Py_DECREF(p);
// throws if it's not a Python string
std::string result(
boost::python::expect_non_null(
PyString_AsString(p)));
Py_DECREF(p); // Done with p
return result;
}
//
// Demonstrate form 1 of handle_exception
//
// Place into result a Python Int object whose value is 1 if a and b have
// identical "__name__" attributes, 0 otherwise.
void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
{
result = PyInt_FromLong(
get_name(a) == get_name(a2));
}
object borrowed_object(PyObject* p)
{
return boost::python::object(
boost::python::handle<>(
boost::python::borrowed(a1)));
}
// 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), borrowed_object(a1), borrowed_object(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(borrowed_object(a1)) == get_name(borrowed_object(a2)));
}
catch(...)
{
// If an exception was thrown, translate it to Python
boost::python::handle_exception();
return 0;
}
}
Revised 13 November, 2002
© Copyright Dave Abrahams 2002.