diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index 95a2805c..cf6bb528 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -21,10 +21,10 @@ namespace boost { namespace python { namespace detail { // base_object - adds a constructor and non-virtual destructor to a // base Python type (e.g. PyObject, PyTypeObject). -template -struct base_object : python_type +template +struct base_object : PythonType { - typedef python_type base_python_type; + typedef PythonType base_python_type; // Initializes type and reference count. All other fields of base_python_type are 0 base_object(PyTypeObject* type_obj); @@ -41,8 +41,8 @@ typedef base_object python_type; // // base_object member function implementations // -template -base_object::base_object(PyTypeObject* type_obj) +template +base_object::base_object(PyTypeObject* type_obj) { base_python_type* bp = this; #if !defined(_MSC_VER) || defined(__STLPORT) @@ -53,8 +53,8 @@ base_object::base_object(PyTypeObject* type_obj) PyObject_INIT(bp, type_obj); } -template -inline base_object::~base_object() +template +inline base_object::~base_object() { Py_DECREF(ob_type); } diff --git a/include/boost/python/detail/cast.hpp b/include/boost/python/detail/cast.hpp index e047c0b3..67fe7b34 100644 --- a/include/boost/python/detail/cast.hpp +++ b/include/boost/python/detail/cast.hpp @@ -15,14 +15,6 @@ namespace boost { namespace python { namespace detail { - // The default way of converting a PyObject* or PyTypeObject* to a T* - template - struct downcast_traits - { - template - static T* cast(U* p) { return static_cast(p); } - }; - inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p) { return reinterpret_cast(p); @@ -54,19 +46,19 @@ template struct downcast { downcast(PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((T*)0, p))) + : m_p(static_cast(detail::as_base_object((T*)0, p))) {} downcast(const PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((const T*)0, p))) + : m_p(static_cast(detail::as_base_object((const T*)0, p))) {} downcast(PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) + : m_p(static_cast(p)) {} downcast(const PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) + : m_p(static_cast(p)) {} operator T*() const { return m_p; } diff --git a/include/boost/python/detail/functions.hpp b/include/boost/python/detail/functions.hpp index 055255e7..16b8e16d 100644 --- a/include/boost/python/detail/functions.hpp +++ b/include/boost/python/detail/functions.hpp @@ -46,7 +46,7 @@ class function : public python_object private: struct type_object; private: - reference m_overloads; + reference m_overloads; // A linked list of the function overloads }; // wrapped_function_pointer<> -- @@ -66,7 +66,12 @@ struct wrapped_function_pointer : function private: PyObject* do_call(PyObject* args, PyObject* keywords) const - { return caller::call(m_pf, args, keywords); } + { + // This is where the boundary between the uniform Python function + // interface and the statically-checked C++ function interface is + // crossed. + return caller::call(m_pf, args, keywords); + } const char* description() const { return typeid(F).name(); } diff --git a/src/functions.cpp b/src/functions.cpp index 71b59136..a04e2e51 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -61,6 +61,8 @@ function::function() PyObject* function::call(PyObject* args, PyObject* keywords) const { + // Traverse the linked list of function overloads until we find one that + // matches. for (const function* f = this; f != 0; f = f->m_overloads.get()) { PyErr_Clear(); @@ -75,9 +77,14 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const } } + // If we get here, no overloads matched the arguments + + // Allow the single-function error-reporting to take effect unless there was + // an overload if (m_overloads.get() == 0) return 0; + // Synthesize a more-explicit error message PyErr_Clear(); string message("No overloaded functions match ("); tuple arguments(ref(args, ref::increment_count)); diff --git a/src/types.cpp b/src/types.cpp index f8cf1ea6..add0ebf0 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -24,6 +24,11 @@ namespace { using detail::type_object_base; + // Define a family of forwarding functions that can be calle from a + // PyTypeObject's slots. These functions dispatch through a (virtual) member + // function pointer in the type_object_base, and handle exceptions in a + // uniform way, preventing us from having to rewrite the dispatching code over + // and over. PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) { try @@ -154,6 +159,10 @@ namespace { extern "C" { +// +// These functions actually go into the type object's slots, and dispatch to the +// "call" wrappers defined above. +// static PyObject* do_instance_repr(PyObject* obj) { return call(obj, &type_object_base::instance_repr);