[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