[C++-sig] How to create a custom exception derived from Exception

Glenn Ramsey gr at componic.co.nz
Tue Jul 31 12:22:11 CEST 2012


On 31/07/12 21:14, 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.
>
> I know it is possible to just wrap and throw my own exception class but it seems
> that because it is not derived from Exception then in certain situations I get
> the error "SystemError: 'finally' pops bad exception".
>
> This example [1] shows how to wrap a C++ exception class...
>
> class MyCPPException : public std::exception {...}
>
> using namespace boost::python;
> ...
>
> PyObject *myCPPExceptionType=0;
>
> void translate(MyCPPException const &e)
> {
>      PyErr_SetObject(myCPPExceptionType, object(e).ptr());
> }
>
>
> BOOST_PYTHON_MODULE(MyModule)
> {
>      ...
>
>      class_<MyCPPException> myCPPExceptionClass("MyCPPException"...);
>      myCPPExceptionClass
>          .def("get_extra_info", &MyCPPException::get_extra_info);
>
>      myCPPExceptionType=myCPPExceptionClass.ptr();
>
>      register_exception_translator<MyCPPException>(&translate);
>      ...
> }
>
> But this is not derived from Exception.
>
> This example [2] shows how to create an exception that is derived from Exception.
>
> PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj =
> PyExc_Exception)
> {
>      using std::string;
>      namespace bp = boost::python;
>
>      string scopeName = bp::extract<string>(bp::scope().attr("__name__"));
>      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;
> }
>
> PyObject* myExceptionTypeObj = 0;
>
> void translate(MyCPPException const &e)
> {
>      PyErr_SetObject(myExceptionTypeObj, object(e).ptr());
> }
>
>
> BOOST_PYTHON_MODULE(MyModule)
> {
>      register_exception_translator<MyCPPException>(&translateFunc);
>      ...
>      myExceptionTypeObj = createExceptionClass("MyException");
>      ...
> }
>
> But this doesn't have any custom methods to get info from the exception.
>
> How can I do both at the same time?
>
> Glenn
>
> [2]
> <http://stackoverflow.com/questions/9620268/boost-python-custom-exception-class>
>
> [1]
> <http://stackoverflow.com/questions/2261858/boostpython-export-custom-exception>

Forgot to mention a couple of things that I tried already...

Passing a tuple of PyExc_Exception and my wrapped custom exception to 
PyErr_NewException, for multiple inheritance, caused an error when attempting to 
load the module in Python, something about incompatible types.

Extracting __dict__ from my wrapped custom exception and passing it to 
PyErr_NewException also caused an error when attempting load the module. I don't 
have it in front of me now but it was complaining about wanting dict instead of 
dictproxy.

Glenn


More information about the Cplusplus-sig mailing list