[C++-sig] Re: Wrapper for exception translation

Gottfried.Ganssauge at HAUFE.DE Gottfried.Ganssauge at HAUFE.DE
Fri Jul 11 12:03:30 CEST 2003


> > ...
> >> 
> >> > Currently, in order to wrap user defined exceptions you need to
> >> >
> >> > - allocate a python exception using PyErr_NewException
> >> 
> >> Well, no.  I don't see any call to PyErr_NewException in
> >> libs/python/test/exception_translator.cpp
> >
> > Right, you don't need to if you are content with RuntimeError
> > exceptions.
> 
> or any other pre-packaged exception type provided by Python.
> 
> > My objective was another one: I wanted to create module exceptions
> > that are derived from the python "Exception" class.
> >> 
> >> >   This function needs to be parametrized using a specific naming
> >> >   convention
> >> 
> >> It's not clear to me what you're referring to.  Are you 
> sure you mean
> >> "naming convention"?
> > Yes.
> > From the documentation to PyErr_NewException:
> >
> > 	... The __module__ attribute of the new class is set to 
> the first part
> > 	(up to the last dot) of the name argument, and the 
> class name is set to
> > 	the last part (after the last dot).
> 
> ...yeah, that's a naming convention, but I don't see how that affects
> the parameterization of any function.
It is enforced by PyErr_NewException, so you must follow this convention.
On the hand I don't think that any user of boost.python is aware of that
convention, so I wanted
to codify it within my facility.

...
> > What I wanted to achieve was the following:
> > Create an instance of a translated_exception_handler<> t 
> which will be
> > registered with the library by calling
> > register_exception_translator<>().
> 
> Sorry to be difficult, but I'm going to contradict you.  You didn't
> want any of that.  What you wanted was to create a new Python
> exception type in the module which would correspond to a particular
> C++ exception type and would be raised at the boundary with Python
> whenever a wrapped function threw the C++ exception.  Right?
Right.
I actually described the way to do it within the current library design.

> 
> > Normally t would be destructed by the end of exception_<>() thereby
> > leaving a registration to a non-existing translator - very bad
> > karma.
> 
> I don't understand any of this.  All you have to pass to
> register_exception_translator is a function pointer, and functions
> live forever.  So where's the lifetime issue?
A pointer to a function which has access to python exception instance e.
As I didn't want to create separate entities I chose to supply a functor
instead which has e as a member variable.

> 
> > Because I didn't like to have an additional container for all
> > translated_exception_handler<> instances, I chose to store t within
> > e's class dictionary.  At that moment it seemed to be the easiest
> > way to create a wrapper class using class_<> instead of making a
> > true python class by hand (and it even works!).  You are right, it
> > is way too complex, I will change it to the mechanism I used in
> > opaque_pointer_converter.
> 
> I don't know what that is, but before you consider doing something
> which is again too complex, please consider:
> 
>     template <class E>
>     struct translate_exception
>     {
>        static char const* msg;
This would need to be defined somewhere.

>        static object python_exception_type;
... and this would need to be defined somewhere as well.

> 
>        static void handler(E const&)
>        {
>             PyErr_SetString(python_exception_type.ptr(), msg.c_str());
>        };
> 
>        translate_exception(char const* python_exception_name, 
> char const* msg_)
>        {
>             // need fancier name manipulation here
>             python_exception_type
>                 = object(
>                     handle<>(PyErr_NewException(name)));
>             msg = msg_;
>             register_exception_translator<E>(handler);
>        }
>     };
> 
> 
> Simple.
Yes.
...
> > I'll make a redesign ...
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).

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.

This would allow us to have true Python exceptions in a pythonic sense
directly wrapped around the corresponding C++ exception.

> > Thnx for your feedback.
> 
> Cool!  Looking forward to it.
> 
> -- 
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com
Cheers,

Gottfried

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030711/90e6d76e/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: exception.hpp
Type: application/octet-stream
Size: 4136 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030711/90e6d76e/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: exception.cpp
Type: application/octet-stream
Size: 1854 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030711/90e6d76e/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: exception.py
Type: application/octet-stream
Size: 2356 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030711/90e6d76e/attachment-0002.obj>


More information about the Cplusplus-sig mailing list