[C++-sig] bad exception conversion
Jim Bosch
talljimbo at gmail.com
Thu Jun 14 01:02:21 CEST 2012
On 06/13/2012 06:31 AM, Wichert Akkerman wrote:
> I have some glue code that calls a C++ function which can raise an
> unsuitable_error exception. I have an exception translator which will
> convert that to a more pythonic version (UnsuitableError), but when I
> use that I get an "SystemError: 'finally' pops bad exception" error on
> the python side. As far as I can see my code looks correct, but I
> suspect I am overlooking something trivial somewhere.
>
>
> using namespace boost::python;
>
> class UnsuitableError : public std::exception {
> public:
> UnsuitableError() : reasons() { }
> ~UnsuitableError() throw() {}
> boost::python::list reasons;
> };
>
> namespace {
> PyObject *UnsuitableErrorType = NULL;
>
> void translator(const unsuitable_error &e) {
> std::list<const char*>::const_iterator i;
> PyObject* unicode;
> UnsuitableError error=UnsuitableError();
> for (i=e.reasons.begin(); i!=e.reasons.end(); i++) {
> unicode = PyUnicode_FromString(*i);
> error.reasons.append(boost::python::object(boost::python::handle<>(unicode)));
>
> }
>
> boost::python::object exc(error);
> PyErr_SetObject(UnsuitableErrorType, exc.ptr());
> }
> }
>
>
> void export() {
> object
> module(handle<>(borrowed(PyImport_AddModule("mypkg.article"))));
> scope().attr("article")=module;
> scope module_scope = module;
>
> class_<UnsuitableError> UnsuitableErrorClass("UnsuitableError");
> UnsuitableErrorClass.def_readonly("reasons",
> &UnsuitableError::reasons);
> UnsuitableErrorType=UnsuitableErrorClass.ptr();
>
> register_exception_translator<unsuitable_error>(&translator);
> }
I suspect the problem is that your custom exception doesn't derived from
Python's built-in Exception base class. Unfortunately, it's impossible
to do that with a Boost.Python wrapped class, but you can get it all
done with the Python C API:
namespace {
PyObject *UnsuitableErrorType = NULL;
void translator(const unsuitable_error &e) {
std::list<const char*>::const_iterator i;
PyObject* unicode;
boost::python::list reasons;
for (i=e.reasons.begin(); i!=e.reasons.end(); i++) {
boost::python::handle<> unicode(PyUnicode_FromString(*i));
reasons.append(boost::python::object(unicode));
}
boost::python::handle<> error(
PyObject_CallFunctionObjArgs(
UnsuitableErrorType, NULL
)
);
PyObject_SetAttrString(error.get(), "reasons", reasons.get());
PyErr_SetObject(UnsuitableErrorType, error.get());
}
}
void export() {
object module(handle<>(borrowed(PyImport_AddModule("mypkg.article"))));
scope().attr("article")=module;
scope module_scope = module;
// NOTE: can use something other than RuntimeError for base class
UnsuitableErrorType = PyErr_NewException(
"UnsuitableError", PyExc_RuntimeError, NULL
);
module_scope.attr("UnsuitableError") =
object(handle<>(borrowed(UnsuitableErrorType)));
register_exception_translator<unsuitable_error>(&translator);
}
I haven't tested any of that, but hopefully it's close enough to point
you in the right direction.
Jim
More information about the Cplusplus-sig
mailing list