[C++-sig] bad exception conversion

2012-06-13 Thread Wichert Akkerman
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);
}
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] bad exception conversion

2012-06-13 Thread Jim Bosch

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