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_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_ UnsuitableErrorClass("UnsuitableError");
UnsuitableErrorClass.def_readonly("reasons",
&UnsuitableError::reasons);
UnsuitableErrorType=UnsuitableErrorClass.ptr();
register_exception_translator(&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_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(&translator);
}
I haven't tested any of that, but hopefully it's close enough to point
you in the right direction.
Jim
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig