On 11/07/2011 09:19 PM, Nick Rasmussen wrote:
I'm cleaning up some of our python bindings for public release as
part of the openexr distribution, and wanted to update the python
bindings of our exception library, Iex, to use boost::python.

The first thing I did was the trivial binding of the class hierarchy
out to python, and performed register_exception_translator<>  for each
type with a translator like:

void
translateExc(const BaseExc&exc)
{
     PyErr_SetObject(pytype,boost::python::object(exc).ptr());
}

where pytype is the pointer to the type object for BaseExc's
python binding.  This allows instances of the exception types
to be raised in c++, translated into python, and caught.

However, the problem I'm having is this: to allow instances of
the exception types to be raised in python (or in fact to have
a try/except/else block finalize properly), the python objects
need to be derived from the python Exception type or one of
its subclasses.


This is a tough problem, and one I think Boost.Python wasn't designed to do, since most of it was in place before one could even derive from Python builtins using the C-API. It's definitely something I'd like to fix in the future.

In the meantime, I've essentially followed the "parallel pure-Python exception hierarchy" method, but you can do some metaprogramming tricks to keep from having to actually build the Python hierarchy yourself. In other words, write some Python code that inspects your Boost.Python-wrapped C++ exception hierarchy and calls type(...) to make corresponding Python types that derive from Exception. The pure-Python exceptions can then be set as class members of the Boost.Python-wrapped C++ exceptions, so your translate functions can do something like this:

void translateExc(const BaseExc & exc) {
    bp::object wrappedExc(exc);
    bp::object pyExcType = wrappedExc.attr("_pyExcType")
    // assume the constructor for the Python exception accepts a
    // C++ exception; useful if the C++ exception has data
    bp::object pyExc = pyExcType(wrappedExc);
    PyErr_SetObject(pyExcType.ptr(), pyExc.ptr());
}

To finish it off, you could add a from-Python converter that converts the pure-Python exception back to the appropriate C++ exception when it's passed to Boost.Python-wrapped functions, but that isn't always necessary.

I don't have any code to do the metaprogramming bits on hand, but I'm happy to help further if you have questions.

By the way, I do hope someone else has an even better idea - my approach is more complicated than it ought to be, but at least it's all overhead rather than something that scales with the number of exceptions you have.

Good luck!

Jim
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to