diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp index a1cdbbb0..66f15587 100644 --- a/include/boost/python/errors.hpp +++ b/include/boost/python/errors.hpp @@ -9,13 +9,50 @@ #ifndef ERRORS_DWA052500_H_ # define ERRORS_DWA052500_H_ +# include + namespace boost { namespace python { struct error_already_set {}; struct argument_error : error_already_set {}; +struct object_functor_base +{ + typedef PyObject* result_type; + virtual PyObject* operator()() const = 0; + private: + static void* operator new(std::size_t); // don't allow dynamic allocation + void operator delete(void*); + void operator delete(void*, size_t); +}; + +template +struct object_functor : object_functor_base +{ + object_functor(T const& f) + : m_f(f) + { + } + + PyObject* operator()() const + { + return m_f(); + } + private: + T const& m_f; +}; + + // Handles exceptions caught just before returning to Python code. -void handle_exception(); +PyObject* handle_exception_impl(object_functor_base const& f); + +template +PyObject* handle_exception(T const& f) +{ + return handle_exception_impl(object_functor(f)); +} + +void handle_exception(void (*)()); template T* expect_non_null(T* x) diff --git a/src/extension_class.cpp b/src/extension_class.cpp index f71976b9..3815a19c 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -10,8 +10,9 @@ // 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) #include -#include #include +#include +#include namespace boost { namespace python { namespace detail { @@ -484,16 +485,19 @@ void operator_dispatcher_dealloc(PyObject* self) int operator_dispatcher_coerce(PyObject** l, PyObject** r) { Py_INCREF(*l); - try + PyObject* new_r = handle_exception( + bind(operator_dispatcher::create, + ref(*r, ref::increment_count), + ref())); + if (new_r) { - *r = operator_dispatcher::create(ref(*r, ref::increment_count), ref()); + *r = new_r; + return 0; } - catch(...) + else { - handle_exception(); return -1; } - return 0; }