diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp deleted file mode 100644 index ae399eed..00000000 --- a/include/boost/python/converter/callback.hpp +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#ifndef CALLBACK_DWA2002228_HPP -# define CALLBACK_DWA2002228_HPP - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -namespace detail -{ - template - struct pointer_callback_from_python - { - pointer_callback_from_python(); - T operator()(PyObject*) const; - }; - - template - struct reference_callback_from_python - { - reference_callback_from_python(); - T operator()(PyObject*) const; - }; - - template - struct rvalue_callback_from_python - { - rvalue_callback_from_python(); - T const& operator()(PyObject*); - private: - rvalue_data m_data; - }; - - template - struct select_callback_from_python - { - BOOST_STATIC_CONSTANT( - bool, ptr = is_pointer::value); - - BOOST_STATIC_CONSTANT( - bool, ref = is_reference::value); - - typedef typename mpl::select_type< - ptr - , pointer_callback_from_python - , typename mpl::select_type< - ref - , reference_callback_from_python - , rvalue_callback_from_python - >::type - >::type type; - }; - - - template - struct reference_callback_to_python : callback_to_python_holder - { - reference_callback_to_python(T& x); - private: - static PyObject* get_object(T& x); - }; - - template - struct value_callback_to_python : callback_to_python_base - { - // Throw an exception if the conversion can't succeed - value_callback_to_python(T const&); - }; - - template - struct pointer_deep_callback_to_python : callback_to_python_base - { - // Throw an exception if the conversion can't succeed - pointer_deep_callback_to_python(Ptr); - }; - - template - struct pointer_shallow_callback_to_python : callback_to_python_holder - { - // Throw an exception if the conversion can't succeed - pointer_shallow_callback_to_python(Ptr); - private: - static PyObject* get_object(Ptr p); - }; - - template - struct select_callback_to_python - { - BOOST_STATIC_CONSTANT( - bool, ptr = is_pointer::value); - - BOOST_STATIC_CONSTANT( - bool, ref_wrapper = is_reference_wrapper::value); - - BOOST_STATIC_CONSTANT( - bool, ptr_wrapper = is_pointer_wrapper::value); - - typedef typename unwrap_reference::type unwrapped_referent; - typedef typename unwrap_pointer::type unwrapped_ptr; - - typedef typename mpl::select_type< - ptr - , pointer_deep_callback_to_python - , typename mpl::select_type< - ptr_wrapper - , pointer_shallow_callback_to_python - , typename mpl::select_type< - ref_wrapper - , reference_callback_to_python - , value_callback_to_python - >::type - >::type - >::type type; - }; -} - -template -struct callback_from_python - : detail::select_callback_from_python::type -{ - typedef T result_type; -}; - -struct void_result -{ - private: - void_result() {} - void operator=(void_result const&); - - // I would prefer to make this completely untouchable, but few - // compilers support template friends -# if 0 - void_result(void_result const&); -# endif - friend struct callback_from_python; -}; - -// Specialization as a convenience for call and call_method -template <> -struct callback_from_python -{ - typedef void_result result_type; - result_type operator()(PyObject* x) const - { - Py_DECREF(expect_non_null(x)); - return result_type(); - } -}; - -template -struct callback_to_python - : detail::select_callback_to_python::type -{ - typedef typename detail::select_callback_to_python::type base; - public: // member functions - // Throw an exception if the conversion can't succeed - callback_to_python(T const& x); -}; - -// Convenience macros for call<> and call_method<> code generation -# define BOOST_PYTHON_CALLBACK_TO_PYTHON_GET(index,ignored) \ - converter::callback_to_python( \ - BOOST_PP_CAT(a,index)).get() - -# define BOOST_PYTHON_ARG_STRING(nargs) \ - "(" BOOST_PP_REPEAT(nargs,BOOST_PYTHON_PROJECT_2ND,"O") ")" - -// -// Implementations -// -namespace detail -{ - template - inline rvalue_callback_from_python::rvalue_callback_from_python() - : m_data(rvalue_from_python_chain::value) - { - throw_if_not_registered(m_data.stage1); - } - - template - inline T const& rvalue_callback_from_python::operator()(PyObject* obj) - { - return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); - } - - BOOST_PYTHON_DECL void throw_no_class_registered(); - - template - inline reference_callback_from_python::reference_callback_from_python() - { - detail::throw_if_not_registered(lvalue_from_python_chain::value); - } - - template - inline T reference_callback_from_python::operator()(PyObject* obj) const - { - return python::detail::void_ptr_to_reference( - callback_convert_reference(obj, lvalue_from_python_chain::value) - , (T(*)())0); - } - - template - inline pointer_callback_from_python::pointer_callback_from_python() - { - detail::throw_if_not_registered(lvalue_from_python_chain::value); - } - - template - inline T pointer_callback_from_python::operator()(PyObject* obj) const - { - return T(callback_convert_pointer(obj, lvalue_from_python_chain::value)); - } - - template - inline value_callback_to_python::value_callback_to_python(T const& x) - : callback_to_python_base(&x, to_python_function::value) - { - } - - template - inline pointer_deep_callback_to_python::pointer_deep_callback_to_python(Ptr x) - : callback_to_python_base(x, pointee_to_python_function::value) - { - } - - template - inline PyObject* reference_callback_to_python::get_object(T& x) - { - to_python_indirect convert; - if (!convert.convertible()) - throw_no_class_registered(); - return convert(x); - } - - template - inline reference_callback_to_python::reference_callback_to_python(T& x) - : callback_to_python_holder(get_object(x)) - { - } - - template - inline pointer_shallow_callback_to_python::pointer_shallow_callback_to_python(Ptr x) - : callback_to_python_holder(get_object(x)) - {} - - template - inline PyObject* pointer_shallow_callback_to_python::get_object(Ptr x) - { - to_python_indirect convert; - if (!convert.convertible()) - throw_no_class_registered(); - return x ? convert(x) : python::detail::none(); - } -} - -template -inline callback_to_python::callback_to_python(T const& x) - : base(x) -{} - -}}} // namespace boost::python::converter - -#endif // CALLBACK_DWA2002228_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp deleted file mode 100644 index d2fb4db2..00000000 --- a/include/boost/python/converter/from_python.hpp +++ /dev/null @@ -1,288 +0,0 @@ -#error obsolete -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#ifndef FROM_PYTHON_DWA2002127_HPP -# define FROM_PYTHON_DWA2002127_HPP - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python -{ - template struct from_python; -}} - -namespace boost { namespace python { namespace converter { - -struct from_python_base -{ - public: // member functions - from_python_base(void* result); - from_python_base(PyObject*, lvalue_from_python_registration const* chain); - bool convertible() const; - - protected: // member functions - void*const& result() const; - - private: // data members - void* m_result; -}; - -// Used when T == U*const& -template -struct pointer_const_reference_from_python -{ - typedef T result_type; - - pointer_const_reference_from_python(PyObject*); - T operator()(PyObject*) const; - bool convertible() const; - - private: - typename detail::referent_storage::type m_result; -}; - -// Used when T == U* -template -struct pointer_from_python : from_python_base -{ - typedef T result_type; - - pointer_from_python(PyObject*); - T operator()(PyObject*) const; -}; - -// Used when T == U& and (T != V const& or T == W volatile&) -template -struct reference_from_python : from_python_base -{ - typedef T result_type; - - reference_from_python(PyObject*); - T operator()(PyObject*) const; -}; - -// ------- rvalue converters --------- - -// Used for the case where T is a non-pointer, non-reference type OR -// is a const non-volatile reference to a non-pointer type. -template -struct rvalue_from_python -{ - typedef typename boost::add_reference< - typename boost::add_const::type - >::type result_type; - - rvalue_from_python(PyObject*); - bool convertible() const; - - result_type operator()(PyObject*); - - private: - rvalue_data m_data; -}; - -// ------- back-reference converters -------- - -// Converts to a (PyObject*,T) bundle, for when you need a reference -// back to the Python object - -template -struct back_reference_from_python - : boost::python::from_python -{ - typedef T result_type; - - back_reference_from_python(PyObject*); - T operator()(PyObject*); - private: - typedef boost::python::from_python base; -}; - -template -struct select_from_python -{ - BOOST_STATIC_CONSTANT( - bool, ptr = is_pointer::value); - - BOOST_STATIC_CONSTANT( - bool, ptr_cref - = boost::python::detail::is_reference_to_pointer::value - && boost::python::detail::is_reference_to_const::value - && !boost::python::detail::is_reference_to_volatile::value); - - - BOOST_STATIC_CONSTANT( - bool, ref = - boost::python::detail::is_reference_to_non_const::value - || boost::python::detail::is_reference_to_volatile::value); - - BOOST_STATIC_CONSTANT( - bool, back_ref = - boost::python::is_back_reference::value); - - typedef typename mpl::select_type< - ptr - , pointer_from_python - , typename mpl::select_type< - ptr_cref - , pointer_const_reference_from_python - , typename mpl::select_type< - ref - , reference_from_python - , typename mpl::select_type< - back_ref - , back_reference_from_python - , rvalue_from_python - >::type - >::type - >::type - >::type type; -}; - -// -// implementations -// -inline from_python_base::from_python_base(void* result) - : m_result(result) -{ -} - -inline from_python_base::from_python_base( - PyObject* source - , lvalue_from_python_registration const* chain) - : m_result(find(source, chain)) -{ -} - -inline bool from_python_base::convertible() const -{ - return m_result != 0; -} - -inline void*const& from_python_base::result() const -{ - return m_result; -} - -// -------- - -namespace detail -{ - template - struct null_ptr_owner - { - static T value; - }; - template T null_ptr_owner::value = 0; - - template - inline U& null_ptr_reference(U&(*)()) - { - return null_ptr_owner::value; - } -} - -template -inline pointer_const_reference_from_python::pointer_const_reference_from_python(PyObject* p) -{ - python::detail::write_void_ptr_reference( - m_result.bytes - , p == Py_None ? p : find(p, lvalue_from_python_chain::value) - , (T(*)())0); -} - -template -inline bool pointer_const_reference_from_python::convertible() const -{ - return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; -} -template -inline T pointer_const_reference_from_python::operator()(PyObject* p) const -{ - return (p == Py_None) - ? detail::null_ptr_reference((T(*)())0) - : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); -} - -// -------- - -template -inline pointer_from_python::pointer_from_python(PyObject* p) - : from_python_base(p == Py_None ? p : find(p, lvalue_from_python_chain::value)) -{ -} - -template -inline T pointer_from_python::operator()(PyObject* p) const -{ - return (p == Py_None) ? 0 : T(result()); -} - -// -------- - -template -inline reference_from_python::reference_from_python(PyObject* p) - : from_python_base(find(p,lvalue_from_python_chain::value)) -{ -} - -template -inline T reference_from_python::operator()(PyObject*) const -{ - return python::detail::void_ptr_to_reference(result(), (T(*)())0); -} - -// ------- - -template -inline rvalue_from_python::rvalue_from_python(PyObject* obj) - : m_data(find(obj, rvalue_from_python_chain::value)) -{ -} - -template -inline bool rvalue_from_python::convertible() const -{ - return m_data.stage1.convertible != 0; -} - -template -inline typename rvalue_from_python::result_type -rvalue_from_python::operator()(PyObject* p) -{ - if (m_data.stage1.construct != 0) - m_data.stage1.construct(p, &m_data.stage1); - - return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); -} - -template -back_reference_from_python::back_reference_from_python(PyObject* x) - : base(x) -{ -} - -template -inline T -back_reference_from_python::operator()(PyObject* x) -{ - return T(x, base::operator()(x)); -} - -}}} // namespace boost::python::converter - -#endif // FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index a465bd81..4e391c5c 100755 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -164,35 +164,32 @@ namespace api const_object_slice slice(object_cref, slice_nil) const; object_slice slice(object_cref, slice_nil); - -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 - template - const_object_slice - slice(T const& start, V const& end) const; - - template - object_slice - slice(T const& start, V const& end); -# else template const_object_slice slice(T const& start, V const& end) const +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else { return this->slice( slice_bound::type(start) , slice_bound::type(end)); } +# endif template object_slice slice(T const& start, V const& end) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else { return this->slice( slice_bound::type(start) , slice_bound::type(end)); } -# endif +# endif private: // there is a confirmed CWPro8 codegen bug here. We prevent the // early destruction of a temporary by binding a named object @@ -204,35 +201,42 @@ namespace api # endif }; - class object : public object_operators + // VC6 and VC7 require this base class in order to generate the + // correct copy constructor for object. We can't define it there + // explicitly or it will complain of ambiguity. + struct object_base : object_operators + { + // copy constructor without NULL checking, for efficiency. + object_base(object_base const&); + object_base(PyObject* ptr); + + object_base& operator=(object_base const& rhs); + ~object_base(); + + // Underlying object access -- returns a borrowed reference + PyObject* ptr() const; + + private: + PyObject* m_ptr; + }; + + class object : public object_base { public: -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - // copy constructor without NULL checking, for efficiency. This - // confuses VC6/7 so object_initializer also handles this case. - object(object const&); -# endif - // explicit conversion from any C++ object to Python template explicit object(T const& x) - : m_ptr(object_initializer::value>::get( + : object_base(object_initializer::value>::get( x, detail::convertible::check(&x))) { } // Throw error_already_set() if the handle is null. explicit object(handle<> const&); - - // Underlying object access -- returns a borrowed reference - PyObject* ptr() const; public: // implementation detail -- for internal use only explicit object(detail::borrowed_reference); explicit object(detail::new_reference); - - private: - PyObject* m_ptr; }; // @@ -327,26 +331,42 @@ namespace converter // inline object::object(handle<> const& x) - : m_ptr(incref(expect_non_null(x.get()))) + : object_base(incref(expect_non_null(x.get()))) {} -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING // copy constructor without NULL checking, for efficiency -inline object::object(object const& rhs) +inline api::object_base::object_base(object_base const& rhs) : m_ptr(incref(rhs.m_ptr)) {} -# endif + +inline api::object_base::object_base(PyObject* p) + : m_ptr(p) +{} + +inline api::object_base& api::object_base::operator=(api::object_base const& rhs) +{ + Py_INCREF(rhs.m_ptr); + Py_DECREF(this->m_ptr); + this->m_ptr = rhs.m_ptr; + return *this; +} + + +inline api::object_base::~object_base() +{ + Py_DECREF(m_ptr); +} inline object::object(detail::borrowed_reference p) - : m_ptr(incref((PyObject*)p)) + : object_base(incref((PyObject*)p)) {} inline object::object(detail::new_reference p) - : m_ptr(expect_non_null((PyObject*)p)) + : object_base(expect_non_null((PyObject*)p)) {} -inline PyObject* object::ptr() const +inline PyObject* api::object_base::ptr() const { return m_ptr; } diff --git a/test/object.py b/test/object.py index 54744809..02da5ce8 100644 --- a/test/object.py +++ b/test/object.py @@ -62,6 +62,8 @@ >>> obj_const_getitem(d, 'foo') 1 >>> obj_setitem42(d, 'foo') +>>> obj_getitem(d, 'foo') +42 >>> d['foo'] 42 >>> obj_moveitem(d, 'foo', 'bar') @@ -92,6 +94,22 @@ >>> class X: pass ... >>> assert check_inplace(range(3), X()) + + + Now make sure that object is actually managing reference counts + +>>> import weakref +>>> class Z: pass +... +>>> z = Z() +>>> def death(r): print 'death' +... +>>> r = weakref.ref(z, death) +>>> z.foo = 1 +>>> obj_getattr(z, 'foo') +1 +>>> del z +death ''' def run(args = None):