2

Based on Boost 1.88.0, boost::python Export Custom Exception and linked discussions I'm using the following to expose a custom C++ std::exception to python.

class cException : public std::exception
{
  private:
    const std::string m_message;
    const int m_code;

  public:
    cException(const std::string &message, const int &code = -1);
    virtual ~cException() throw();
    const std::string &message() const;
    const int &code() const;
};

template <class ExceptionCustomType>
class exception_ : public boost::python::class_<ExceptionCustomType>
{
  private:
    std::string m_exc_name;

  public:
    template <class ExceptionBaseType>
    exception_(char const* excName, ExceptionBaseType excBaseType) : boost::python::class_<ExceptionCustomType>(excName, boost::python::no_init), m_exc_name(excName)
    {
        PyObject* excType = PyErr_NewException((std::string(boost::python::extract<std::string>(boost::python::scope().attr("__name__"))) + std::string(".") + this->m_exc_name).c_str(), excBaseType, 0);
        boost::python::scope().attr(this->m_exc_name.c_str()) = boost::python::handle<>(boost::python::borrowed(excType));

        boost::python::register_exception_translator<ExceptionCustomType>(
          [ptr=excType](const ExceptionCustomType& e) {
            boost::python::object excObj(boost::python::handle<>(boost::python::borrowed(ptr)));
            excObj.attr("__repr__") = boost::python::str(e.message());
            excObj.attr("code")     = boost::python::object(e.code());
            PyErr_SetString(ptr, e.message().c_str());
            PyErr_SetObject(ptr, boost::python::object(e).ptr());
        });
    }
};

BOOST_PYTHON_MODULE(MyModule)
{
  exception_<cException>("MyCustomException", PyExc_BaseException)
  ;
}

In Python then this works like this:

import MyModule

try:
  MyModule.throw()
except MyModule.MyCustomException as e:
  print("REPR = ", e.__repr__)
  print("CODE = ", e.code)

But I don't like it that the attributes "__repr__" and "code" are set in the register_exception_translator. I would prefer to set them in the python exception definition itself. E.g.

BOOST_PYTHON_MODULE(MODULENAME)
{
  exception_<cException>("MyCustomException", PyExc_BaseException)
    .add_property("__repr__", &cException::message)
    .add_property("code", &cException::code)
    .def("some_additional_fancy_method", &cException::some_additional_fancy_method)
  ;
}

I have failed to implement this so far. Does anyone who is more familiar with boost::python know whether this can be realized at all or how?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.