[C++-sig] Re: Wrapper for exception translation
David Abrahams
dave at boost-consulting.com
Sun Jul 13 05:28:20 CEST 2003
Gottfried,
I could've sworn I replied to this, but now I can't find the reply
anywhere.
Gottfried.Ganssauge at HAUFE.DE writes:
> At times you don't see the forrest, just trees ...
> I think this time I have a simple facility which is also easy to use (no
> macros).
Looks pretty good; I still have a few criticisms.
> It could be even simpler with a completely different design but frankly - I
> have no clue how to implement that:
> We would need a way to somehow derive (in the python sense) a class_<> from
> PyExc_Exception (the type of the python Exception class) or any other python
> class (PyErr_NewException() has a base parameter, which could be used for
> that).
>
> At the same time an exception_translator should be registered for that
> class_<> which uses PyErr_SetObject() to raise a copy of the exception
> caught.
None of that sounds simpler to me.
> This would allow us to have true Python exceptions in a pythonic sense
> directly wrapped around the corresponding C++ exception.
Doesn't sound like a big advantage to me, but I guess if you had
stored data members in the C++ exception type you'd want them to be
preserved. Hmm, there's no reason you can't build a BPL extension
class which also inherits from Exception, but it seems tough.
> /**
> * Register an exception translator for the Template argument.
> *
> * @param name
> * the name for the new exception.
> * This name is registered in the current scope.
> *
> * @param base
> * An optional base class this exception should be derived from
> *
> * @return
> * A handle to the newly allocated exception
> */
> template <class Exception>
> handle<> exception_ (
> const char *name,
> handle<> base = handle<>(),
> boost::type<Exception>* = 0) {
> // Name of the new exception
> str exc_name (detail::module_prefix() + "." + name);
> // C-Representation of the exception name
> const char *cname = extract<const char *> (exc_name);
>
> // Allocate a new exception
> handle<> e (
> PyErr_NewException (const_cast<char *> (cname), base.get(), 0));
>
> // Register a handler for it with the library
> register_exception_translator<Exception> (
> detail::translated_exception_handler<Exception> (e));
>
> // and make it visible in the scope's namespace
> scope().attr (name) = e;
> return (e);
> }
> }} // namespace boost::python
> # endif // BOOST_PYTHON_EXCEPTION_HPP_
<snip>
> BOOST_PYTHON_MODULE(exception_ext) {
> handle<> e (exception_<exc> ("exc"));
> exception_<bad_exc> ("bad_exc");
> exception_<obj_exc> ("obj_exc");
> exception_<derived_exc> ("derived_exc", e);
>
> def ("throw_exc", &throw_exc);
> def ("throw_bad_exc", &throw_bad_exc);
> def ("throw_exc3", &throw_exc3);
> def ("throw_derived", &throw_derived);
>
> {
> scope x (class_<exc> ("exc_def"));
>
> // a nested exception within class exc_def
> exception_<exc3> ("exc3");
> }
>
> class_<obj_exc> ("obj_exception")
> .def ("throw", &obj_exc::raise)
> .def ("what", &obj_exc::what)
> ;
> }
This is a big improvement. What I don't like about this is:
a. the need for users to mess with handle<>s. handle<> can be
nil, so is less safe than object.
b. a name in the public interface ("exception_") which
needlessly ends in an underscore
c. Formatting inconsistent with the library and goofy @directives
in the comments <wink>
I'd prefer an interface where boost::python::exception was a class
derived from object:
exception<exc> e("exc");
exception<bad_exc>("bad_exc");
exception<obj_exc>("obj_exc");
exception<derived_exc>("derived_exc", e);
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list