[C++-sig] How to create a custom exception derived from Exception
Glenn Ramsey
gr at componic.co.nz
Wed Aug 1 02:07:08 CEST 2012
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
More information about the Cplusplus-sig
mailing list