|
|
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_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.
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.