Hi, I'm wrapping a C++ library that's actually just a thin wrapper around a C lib.
Through a dispatch() method of a Dispatcher class there's an invocation of callbacks which get implemented on the Python side, by subclassing callback classes exposed through Boost.Python. Now, for performing the actual dispatch the C++ library calls into the underlying C library. This hasn't been a problem so far as we've been targetting Solaris using Sun/Oracle studio compilers. However, on Linux compiled with GCC, if an exception gets raised in the Python callback the program segfaults. Obviously the C part of the vendor library has not been compiled with (GCC-) exception support for Linux. Unfortunately this isn't under my control and the library provider seems not to be willing to make the library robust against exceptions in user callback code. So I need to keep the Boost C++ exception that "signals" the Python exception from passing through the C parts. Instead of introducing some custom error/exception notification scheme I *think* I can simply do this: As I need wrapper classes for the virtual method override mechanisms anyway I can just ignore/suppress the exception in the callback wrapper layer and re-throw the exception again in the dispatcher, provided that in between we do not return to Python and no other call into Python is made: I.e. The callback wrapper simply suppresses the C++ exception "signalled" for the Python exception: class CallbackWrap : public Callback, public bp::wrapper<Callback> { // pure virtual so no need for default implementation // virtual void onMsg(MsgListener* listener, Msg& msg) = 0; virtual void onMsg(MsgListener* listener, Msg& msg) { try { this->get_override("onMsg")(bp::ptr(listener), boost::ref (msg)); } catch (const bp::error_already_set& e) { if (PyErr_Occurred()) { // Do nothing: The Dispatcher that invoked the callback // MUST check if a Python error has been set and re-throw } } } }; The Dispatcher is then responsible for re-throwing, to not let the Python exception go undetected when returning to the Python world: // virtual Status dispatch (); virtual Status dispatch() { Status ret; if (bp::override f = this->get_override("dispatch")) { ret = f(); // *note* } else { ret = Queue::dispatch(); } if (PyErr_Occurred()) { // Re-throw the error that stems from the Python exception in the dispatched callback bp::throw_error_already_set(); } return ret; } Does this sound sane? Any hints appreciated, Holger Landesbank Baden-Wuerttemberg Anstalt des oeffentlichen Rechts Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz HRA 12704 Amtsgericht Stuttgart _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig