On 31/07/12 22:58, Jim Bosch wrote:
On 07/31/2012 06:14 PM, Glenn Ramsey wrote:
Using boost::python how can I create an a custom exception that is
derived from Python's Exception? The functionality I would like to get
by doing this is to provide additional methods for the catching code to
retrieve information from the exception.
The approach I've taken in the past (sorry, don't have an example right now) is
to raise a true Python exception (from PyErr_NewException), and attach your
Boost.Python-wrapped C++ exception to it as an instance variable. Then put a
__getattr__ in the true Python exception that forwards to the Boost.Python
object it holds.
I can try to reconstruct more details if needed, but hopefully that's enough to
get you started.
Thanks, based on that I have done this, which seems to work, but I'm not sure if
it is entirely correct. I didn't need to implement __getattr__ and would be
interested in seeing some more details of your approach.
PyObject *exceptionType=NULL; // will be initialised inside
BOOST_PYTHON_MODULE(...) using createExceptionClass(...)
void translator(const MyCPPException &x) {
bp::object exc(x);
bp::object exc_t(bp::handle<>(bp::borrowed(exceptionType)));
exc_t.attr("cause") = exc;
PyErr_SetString(exceptionType, x.what());
}
PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj =
PyExc_Exception)
{
std::string scopeName = bp::extract<std::string
(bp::scope().attr("__name__"));
std::string qualifiedName0 = scopeName + "." + name;
char* qualifiedName1 = const_cast<char*>(qualifiedName0.c_str());
PyObject* typeObj = PyErr_NewException(qualifiedName1, baseTypeObj, 0);
if(!typeObj)
{
bp::throw_error_already_set();
}
bp::scope().attr(name) = bp::handle<>(bp::borrowed(typeObj));
return typeObj;
}
BOOST_PYTHON_MODULE(MyModule)
{
bp::register_exception_translator<MyCPPException>(translator);
....
bp::class_<MyCPPException>("MyCPPException")
.def(...);
exceptionType = createExceptionClass("MyCPPExceptionType");
....
}
In Python:
try:
...
except MyModule.MyCPPExceptionType as e:
cause = e.cause # wrapped exception can be accessed here
...
Glenn
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig