3

The accepted answer to boost::python Export Custom Exception shows how to export a custom exception class from C++, and Boost.Python custom exception class shows how to export an exception class that inherits from Python's Exception. How can I do both? That is expose an exception class that has custom methods to retrieve information and also have that class be derived from Python's Exception.

Community
  • 1
  • 1
glennr
  • 2,069
  • 2
  • 26
  • 37

1 Answers1

5

A workable solution, suggested by Jim Bosch on the C++-sig list, is to use composition instead of inheriting from the wrapped C++ exception. The code must create a Python exception as is done here, and then add the wrapped C++ exception as an instance variable of the Python exception.

void translator(const MyCPPException &x) {
    bp::object exc(x); // wrap the C++ exception

    bp::object exc_t(bp::handle<>(bp::borrowed(exceptionType)));
    exc_t.attr("cause") = exc; // add the wrapped exception to the Python exception

    PyErr_SetString(exceptionType, x.what());
}

The wrapped C++ exception can then be accessed from Python like this:

try:
    ...
except MyModule.MyCPPExceptionType as e:
    cause = e.cause # wrapped exception can be accessed here

but the exception will also be caught by

try:
    ...
except Exception:
    ...
Community
  • 1
  • 1
glennr
  • 2,069
  • 2
  • 26
  • 37
  • 2
    Note that `exc_t.attr("cause") = exc;` adds the C++ exception instance as an attribute to the Python exception *class*. So if you caught an exception instance e1 in Python and kept a reference to it a second raise of such a C++ exception would change the cause attribute of e1 to refer to the new C++ exception instance. – Holger Apr 24 '15 at 09:24