From 366ee6d24b6c88f93fe9945eb06eba3f0bf30102 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 12 Jun 2002 21:59:17 +0000 Subject: [PATCH] reference<> => handle<> [SVN r14136] --- Jamfile | 2 +- include/boost/python/back_reference.hpp | 10 +- include/boost/python/cast.hpp | 96 ++++ include/boost/python/class.hpp | 28 +- .../boost/python/converter/arg_to_python.hpp | 10 +- .../python/converter/arg_to_python_base.hpp | 33 +- .../python/converter/builtin_converters.hpp | 7 +- .../converter/callback_to_python_base.hpp | 53 --- include/boost/python/detail/module_base.hpp | 15 +- include/boost/python/detail/wrap_function.hpp | 2 +- include/boost/python/from_python.hpp | 53 --- include/boost/python/handle.hpp | 223 +++++++++ include/boost/python/iterator.hpp | 12 +- include/boost/python/module.hpp | 4 +- include/boost/python/object/class.hpp | 18 +- .../boost/python/object/class_converters.hpp | 2 +- include/boost/python/object/class_wrapper.hpp | 8 +- include/boost/python/object/function.hpp | 4 +- include/boost/python/object/iterator.hpp | 20 +- include/boost/python/object/iterator_core.hpp | 4 +- include/boost/python/objects.hpp | 17 +- include/boost/python/objects2.hpp | 348 ++++++++++++++ include/boost/python/operators2.hpp | 2 +- include/boost/python/reference.hpp | 21 +- include/boost/python/to_python_indirect.hpp | 2 +- src/converter/builtin_converters.cpp | 4 +- src/converter/callback.cpp | 8 +- src/errors.cpp | 7 - src/module.cpp | 28 +- src/object/class.cpp | 52 ++- src/object/function.cpp | 6 +- src/object/iterator.cpp | 6 +- src/objects2.cpp | 426 ++++++++++++++++++ test/Jamfile | 4 + test/cltree.cpp | 3 + test/upcast.cpp | 19 + 36 files changed, 1264 insertions(+), 293 deletions(-) create mode 100755 include/boost/python/cast.hpp delete mode 100644 include/boost/python/converter/callback_to_python_base.hpp delete mode 100644 include/boost/python/from_python.hpp create mode 100755 include/boost/python/handle.hpp create mode 100755 include/boost/python/objects2.hpp create mode 100755 src/objects2.cpp create mode 100755 test/upcast.cpp diff --git a/Jamfile b/Jamfile index 19b269b0..23d82c1b 100644 --- a/Jamfile +++ b/Jamfile @@ -23,7 +23,7 @@ dll bpl src/object/life_support.cpp src/errors.cpp src/module.cpp - src/objects.cpp + src/objects2.cpp src/converter/builtin_converters.cpp src/converter/callback.cpp src/object/iterator.cpp diff --git a/include/boost/python/back_reference.hpp b/include/boost/python/back_reference.hpp index bde26dcd..fbfaff11 100644 --- a/include/boost/python/back_reference.hpp +++ b/include/boost/python/back_reference.hpp @@ -6,7 +6,7 @@ #ifndef BACK_REFERENCE_DWA2002510_HPP # define BACK_REFERENCE_DWA2002510_HPP -# include +# include namespace boost { namespace python { @@ -17,10 +17,10 @@ struct back_reference typedef T type; back_reference(PyObject*, T); - ref reference() const; + handle<> reference() const; T get() const; private: - ref m_reference; + handle<> m_reference; T m_value; }; @@ -75,13 +75,13 @@ class is_back_reference // template back_reference::back_reference(PyObject* p, T x) - : m_reference(p, ref::increment_count) + : m_reference(python::borrow(p)) , m_value(x) { } template -ref back_reference::reference() const +handle<> back_reference::reference() const { return m_reference; } diff --git a/include/boost/python/cast.hpp b/include/boost/python/cast.hpp new file mode 100755 index 00000000..9408579a --- /dev/null +++ b/include/boost/python/cast.hpp @@ -0,0 +1,96 @@ +// 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 CAST_DWA200269_HPP +# define CAST_DWA200269_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template struct base_type_traits; + +template <> +struct base_type_traits +{ + typedef PyObject type; +}; + +template <> +struct base_type_traits +{ + typedef PyObject type; +}; + +namespace detail +{ + typedef char* yes_convertible; + typedef int* no_convertible; + + typedef char* yes_python_object; + typedef int* no_python_object; + + template + struct convertible + { + static inline yes_convertible check(Target) { return 0; } + static inline no_convertible check(...) { return 0; } + }; + + template + inline Target* upcast(Target* p, yes_convertible) + { + return p; + } + + template + inline Target* upcast(Source* p, no_convertible, boost::type* = 0) + { + typedef typename base_type_traits::type base; + return detail::upcast((base*)p, convertible::check((base*)0)); + } + + + template + inline Target* downcast(Source* p, yes_convertible) + { + return static_cast(p); + } + + template + inline Target* downcast(Source* p, no_convertible, boost::type* = 0) + { + typedef typename base_type_traits::type base; + return (Target*)detail::downcast(p, convertible::check((base*)0)); + } + + template + inline void assert_castable(boost::type* = 0) + { + typedef char must_be_a_complete_type[sizeof(T)]; + } +} + +template +inline Target* upcast(Source* x, Target* = 0) +{ + detail::assert_castable(); + detail::assert_castable(); + return detail::upcast(x, detail::convertible::check(x)); +} + +template +inline Target* downcast(Source* x, Target* = 0) +{ + detail::assert_castable(); + detail::assert_castable(); + return detail::downcast(x, detail::convertible::check((Target*)0)); +} + +}} // namespace boost::python + +#endif // CAST_DWA200269_HPP diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index ec21ba8e..861d8e72 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -9,7 +9,7 @@ # include # include # include -# include +# include # include # include # include @@ -46,14 +46,14 @@ namespace detail // to the type of holder that must be created. The 3rd argument is a // reference to the Python type object to be created. template - static inline void register_copy_constructor(mpl::bool_t const&, Holder*, ref const& obj, T* = 0) + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, handle<> const& obj, T* = 0) { objects::class_wrapper x(obj); } // Tag dispatched to have no effect. template - static inline void register_copy_constructor(mpl::bool_t const&, Holder*, ref const&, T* = 0) + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, handle<> const&, T* = 0) { } } @@ -104,7 +104,7 @@ class class_ : public objects::class_base // appropriate. objects::function::add_to_namespace( this->object(), name, - ref(detail::wrap_function( + handle<>(detail::wrap_function( // This bit of nastiness casts F to a member function of T if possible. detail::member_function_cast::stage1(f).stage2((T*)0).stage3(f) ))); @@ -132,7 +132,7 @@ class class_ : public objects::class_base // appropriate. objects::function::add_to_namespace( this->object(), op.name(), - ref(detail::wrap_function(&op_t::template apply::execute))); + handle<>(detail::wrap_function(&op_t::template apply::execute))); return *this; } @@ -176,7 +176,7 @@ class class_ : public objects::class_base template self& def_readonly(char const* name, D T::*pm) { - ref fget(make_getter(pm)); + handle<> fget(make_getter(pm)); this->add_property(name, fget); return *this; } @@ -184,16 +184,16 @@ class class_ : public objects::class_base template self& def_readwrite(char const* name, D T::*pm) { - ref fget(make_getter(pm)); - ref fset(make_setter(pm)); + handle<> fget(make_getter(pm)); + handle<> fset(make_setter(pm)); return this->add_property(name, fget, fset); } // Property creation - self& add_property(char const* name, ref const& fget); - self& add_property(char const* name, ref const& fget, ref const& fset); + self& add_property(char const* name, handle<> const& fget); + self& add_property(char const* name, handle<> const& fget, handle<> const& fset); - self& setattr(char const* name, ref const&); + self& setattr(char const* name, handle<> const&); private: // types typedef objects::class_id class_id; @@ -258,21 +258,21 @@ inline class_::class_(char const* name) template -inline class_& class_::add_property(char const* name, ref const& fget) +inline class_& class_::add_property(char const* name, handle<> const& fget) { base::add_property(name, fget); return *this; } template -inline class_& class_::add_property(char const* name, ref const& fget, ref const& fset) +inline class_& class_::add_property(char const* name, handle<> const& fget, handle<> const& fset) { base::add_property(name, fget, fset); return *this; } template -inline class_& class_::setattr(char const* name, ref const& x) +inline class_& class_::setattr(char const* name, handle<> const& x) { base::setattr(name, x); return *this; diff --git a/include/boost/python/converter/arg_to_python.hpp b/include/boost/python/converter/arg_to_python.hpp index 6cd9836c..78268fd0 100755 --- a/include/boost/python/converter/arg_to_python.hpp +++ b/include/boost/python/converter/arg_to_python.hpp @@ -11,6 +11,8 @@ # include # include # include +// Bring in specializations +# include namespace boost { namespace python { namespace converter { @@ -19,7 +21,7 @@ namespace detail BOOST_PYTHON_DECL void throw_no_class_registered(); template - struct reference_arg_to_python : arg_to_python_holder + struct reference_arg_to_python : handle<> { reference_arg_to_python(T& x); private: @@ -41,7 +43,7 @@ namespace detail }; template - struct pointer_shallow_arg_to_python : arg_to_python_holder + struct pointer_shallow_arg_to_python : handle<> { // Throw an exception if the conversion can't succeed pointer_shallow_arg_to_python(Ptr); @@ -129,13 +131,13 @@ namespace detail template inline reference_arg_to_python::reference_arg_to_python(T& x) - : arg_to_python_holder(get_object(x)) + : handle<>(get_object(x)) { } template inline pointer_shallow_arg_to_python::pointer_shallow_arg_to_python(Ptr x) - : arg_to_python_holder(get_object(x)) + : handle<>(get_object(x)) {} template diff --git a/include/boost/python/converter/arg_to_python_base.hpp b/include/boost/python/converter/arg_to_python_base.hpp index 7573b499..1e5fe191 100755 --- a/include/boost/python/converter/arg_to_python_base.hpp +++ b/include/boost/python/converter/arg_to_python_base.hpp @@ -7,45 +7,16 @@ # define ARG_TO_PYTHON_BASE_DWA200237_HPP # include # include -# include +# include namespace boost { namespace python { namespace converter { namespace detail { - struct arg_to_python_holder - { - arg_to_python_holder(PyObject* obj); - PyObject* get() const; - PyObject* get_incref() const; - private: - ref m_held; - }; - - struct BOOST_PYTHON_DECL arg_to_python_base : arg_to_python_holder + struct BOOST_PYTHON_DECL arg_to_python_base : handle<> { arg_to_python_base(void const volatile* source, to_python_function_t); }; - - // - // implmentation - // - inline arg_to_python_holder::arg_to_python_holder(PyObject* obj) - : m_held(obj) - { - } - - inline PyObject* arg_to_python_holder::get() const - { - return m_held.get(); - } - - inline PyObject* arg_to_python_holder::get_incref() const - { - PyObject* result = m_held.get(); - Py_XINCREF(result); - return result; - } } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 9d072498..77a78069 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -7,8 +7,7 @@ # define BUILTIN_CONVERTERS_DWA2002124_HPP # include # include -# include -# include +# include # include # include @@ -65,10 +64,10 @@ namespace detail namespace converter \ { \ template <> struct arg_to_python< T > \ - : detail::arg_to_python_holder \ + : handle<> \ { \ arg_to_python(T const& x) \ - : detail::arg_to_python_holder(expr) {} \ + : python::handle<>(expr) {} \ }; \ } diff --git a/include/boost/python/converter/callback_to_python_base.hpp b/include/boost/python/converter/callback_to_python_base.hpp deleted file mode 100644 index d03f2f60..00000000 --- a/include/boost/python/converter/callback_to_python_base.hpp +++ /dev/null @@ -1,53 +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_TO_PYTHON_BASE_DWA200237_HPP -# define CALLBACK_TO_PYTHON_BASE_DWA200237_HPP -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -namespace detail -{ - struct callback_to_python_holder - { - callback_to_python_holder(PyObject* obj); - PyObject* get() const; - PyObject* get_incref() const; - private: - ref m_held; - }; - - struct BOOST_PYTHON_DECL callback_to_python_base : callback_to_python_holder - { - callback_to_python_base(void const volatile* source, to_python_function_t); - }; - - // - // implmentation - // - inline callback_to_python_holder::callback_to_python_holder(PyObject* obj) - : m_held(obj) - { - } - - inline PyObject* callback_to_python_holder::get() const - { - return m_held.get(); - } - - inline PyObject* callback_to_python_holder::get_incref() const - { - PyObject* result = m_held.get(); - Py_XINCREF(result); - return result; - } -} - -}}} // namespace boost::python::converter - -#endif // CALLBACK_TO_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/detail/module_base.hpp b/include/boost/python/detail/module_base.hpp index ecd13aa4..aaa6a135 100644 --- a/include/boost/python/detail/module_base.hpp +++ b/include/boost/python/detail/module_base.hpp @@ -6,7 +6,7 @@ #ifndef MODULE_BASE_DWA2002227_HPP # define MODULE_BASE_DWA2002227_HPP # include -# include +# include namespace boost { namespace python { namespace detail { @@ -19,25 +19,24 @@ class BOOST_PYTHON_DECL module_base // Add elements to the module void setattr(const char* name, PyObject*); - void setattr(const char* name, ref const&); - void add(PyTypeObject* x); // just use the type's name - void add_type(ref); + void setattr(const char* name, handle<> const&); + void add(type_handle const&); // just use the type's name // Return a reference to the Python module object being built - inline ref object() const; + inline handle<> object() const; protected: - void add_class(ref const& class_obj); + void add_class(type_handle const& class_obj); private: - ref m_module; + handle<> m_module; static PyMethodDef initial_methods[1]; }; // // inline implementations // -inline ref module_base::object() const +inline handle<> module_base::object() const { return m_module; } diff --git a/include/boost/python/detail/wrap_function.hpp b/include/boost/python/detail/wrap_function.hpp index 57725efd..71ee967e 100644 --- a/include/boost/python/detail/wrap_function.hpp +++ b/include/boost/python/detail/wrap_function.hpp @@ -31,7 +31,7 @@ template inline PyObject* wrap_function_aux(F f, PyObject*) { return f; } template -inline PyObject* wrap_function_aux(F f, boost::python::reference x) { return x.release(); } +inline PyObject* wrap_function_aux(F f, boost::python::handle x) { return x.release(); } template inline PyObject* wrap_function_aux(F f, ...) { return make_function(f); } diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp deleted file mode 100644 index 4219bc2d..00000000 --- a/include/boost/python/from_python.hpp +++ /dev/null @@ -1,53 +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_DWA2002128_HPP -# define FROM_PYTHON_DWA2002128_HPP - -# include - -namespace boost { namespace python { - -template -struct from_python - : converter::select_arg_from_python::type -{ - typedef typename converter::select_from_python::type base; - from_python(PyObject*); -}; - -// specialization for PyObject* -template <> -struct from_python -{ - typedef PyObject* result_type; - - from_python(PyObject*) {} - bool convertible() const { return true; } - PyObject* operator()(PyObject* source) const { return source; } -}; - -template <> -struct from_python -{ - typedef PyObject* const& result_type; - from_python(PyObject*) {} - bool convertible() const { return true; } - PyObject*const& operator()(PyObject*const& source) const { return source; } -}; - -// -// implementations -// -template -inline from_python::from_python(PyObject* source) - : base(source) -{ -} - -}} // namespace boost::python - -#endif // FROM_PYTHON_DWA2002128_HPP diff --git a/include/boost/python/handle.hpp b/include/boost/python/handle.hpp new file mode 100755 index 00000000..912717e0 --- /dev/null +++ b/include/boost/python/handle.hpp @@ -0,0 +1,223 @@ +// 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 HANDLE_DWA200269_HPP +# define HANDLE_DWA200269_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +inline T* incref(T* p) +{ + Py_INCREF(python::upcast(p)); + return p; +} + +template +inline T* xincref(T* p) +{ + Py_XINCREF(python::upcast(p)); + return p; +} + +template +inline void decref(T* p) +{ + Py_DECREF(python::upcast(p)); +} + +template +inline void xdecref(T* p) +{ + Py_XDECREF(python::upcast(p)); +} + +template struct borrowed; +template struct null_ok; + +template +inline borrowed* borrow(T* p) +{ + return (borrowed*)p; +} + +template +inline null_ok* allow_null(T* p) +{ + return (null_ok*)p; +} + +namespace detail +{ + template + inline T* manage_ptr(borrowed >* p, int) + { + return python::xincref((T*)p); + } + + template + inline T* manage_ptr(null_ok >* p, int) + { + return python::xincref((T*)p); + } + + template + inline T* manage_ptr(borrowed* p, long) + { + return python::incref(expect_non_null((T*)p)); + } + + template + inline T* manage_ptr(null_ok* p, long) + { + return (T*)p; + } + + template + inline T* manage_ptr(T* p, ...) + { + return expect_non_null(p); + } + +#if 0 + template + struct handle_proxy + : handle_proxy::type> + { + typedef typename base_type_traits::type base_t; + handle_proxy(PyObject* p) + : handle_proxy(p) + {} + operator T*() const { return python::downcast(m_p); } + }; + + template <> + struct handle_proxy + { + handle_proxy(PyObject* p) : m_p(p) {} + operator PyObject*() const { return (PyObject*)m_p; } + private: + PyObject* m_p; + }; +#endif +} + +template +class handle +{ + typedef T* (handle::*bool_type); + + public: + handle(); + ~handle(); + + template + handle(Y* p) + : m_p( + python::upcast( + detail::manage_ptr(p, 0) + ) + ) + { + } + + handle& operator=(handle const& r); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + + template + handle& operator=(handle const & r) // never throws + { + python::xdecref(m_p); + m_p = python::xincref(python::upcast(r.get())); + return *this; + } + +#endif + + template + handle(handle const& r) + : m_p(python::xincref(python::upcast(r.get()))) + { + } + + handle(handle const& r) + : m_p(python::xincref(r.m_p)) + { + } + + T* operator-> () const; + T* get() const; + T* release(); + + operator bool_type() const // never throws + { + return m_p ? &handle::m_p : 0; + } + bool operator! () const; // never throws + + private: // data members + T* m_p; +}; + +typedef handle type_handle; + +// +// implementations +// +template +inline handle::handle() + : m_p(0) +{ +} + +template +inline handle::~handle() +{ + python::xdecref(m_p); +} + +template +inline handle& handle::operator=(handle const& r) +{ + python::xdecref(m_p); + m_p = python::xincref(r.m_p); + return *this; +} + +template +inline T* handle::operator->() const +{ + return m_p; +} + +template +inline T* handle::get() const +{ + return m_p; +} + +template +inline bool handle::operator!() const +{ + return m_p == 0; +} + +template +inline T* handle::release() +{ + T* result = m_p; + m_p = 0; + return result; +} + +}} // namespace boost::python + + +#endif // HANDLE_DWA200269_HPP diff --git a/include/boost/python/iterator.hpp b/include/boost/python/iterator.hpp index a31954aa..724b926a 100644 --- a/include/boost/python/iterator.hpp +++ b/include/boost/python/iterator.hpp @@ -19,7 +19,7 @@ namespace detail // objects::make_iterator(...), which allows us to pass member // function and member data pointers. template - inline ref make_iterator( + inline handle<> make_iterator( Accessor1 get_start, Accessor2 get_finish, boost::type* target = 0, NextPolicies* = 0) { return objects::make_iterator_function( @@ -68,7 +68,7 @@ struct iterators // accessors. Deduce the Target type from the accessors. The iterator // returns copies of the inderlying elements. template -ref range(Accessor1 start, Accessor2 finish) +handle<> range(Accessor1 start, Accessor2 finish) { return detail::make_iterator( start, finish @@ -78,7 +78,7 @@ ref range(Accessor1 start, Accessor2 finish) // Create an iterator-building function which uses the given accessors // and next() policies. Deduce the Target type. template -ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) +handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) { return detail::make_iterator(start, finish, detail::target(start)); } @@ -86,7 +86,7 @@ ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) // Create an iterator-building function which uses the given accessors // and next() policies, operating on the given Target type template -ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type* = 0) +handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type* = 0) { typedef typename add_reference::type target; return detail::make_iterator(start, finish); @@ -98,10 +98,10 @@ ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type -struct iterator : ref +struct iterator : handle<> { iterator() - : ref( + : handle<>( range( &iterators::begin, &iterators::end )) diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 38a80dca..23f2884e 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -27,7 +27,7 @@ class module : public detail::module_base // Add elements to the module module& setattr(const char* name, PyObject*); module& setattr(const char* name, PyTypeObject*); - module& setattr(const char* name, ref const&); + module& setattr(const char* name, handle<> const&); module& add(PyTypeObject* x); // just use the type's name template @@ -68,7 +68,7 @@ inline module& module::setattr(const char* name, PyTypeObject* x) return *this; } -inline module& module::setattr(const char* name, ref const& x) +inline module& module::setattr(const char* name, handle<> const& x) { this->base::setattr(name, x); return *this; diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 466b6e44..8cf29b23 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -10,7 +10,7 @@ # include # include # include -# include +# include # include # include @@ -35,15 +35,15 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable ); // Retrieve the underlying object - ref object() const { return m_object; } - void add_property(char const* name, ref const& fget); - void add_property(char const* name, ref const& fget, ref const& fset); - void setattr(char const* name, ref const&); + type_handle object() const { return m_object; } + void add_property(char const* name, handle<> const& fget); + void add_property(char const* name, handle<> const& fget, handle<> const& fset); + void setattr(char const* name, handle<> const&); private: - ref m_object; + type_handle m_object; }; -BOOST_PYTHON_DECL ref registered_class_object(class_id id); +BOOST_PYTHON_DECL type_handle registered_class_object(class_id id); // Each extension instance will be one of these struct instance @@ -52,8 +52,8 @@ struct instance instance_holder* objects; }; -BOOST_PYTHON_DECL ref class_metatype(); -BOOST_PYTHON_DECL ref class_type(); +BOOST_PYTHON_DECL type_handle class_metatype(); +BOOST_PYTHON_DECL type_handle class_type(); }}} // namespace boost::python::objects diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index e396dc25..14e79a9d 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include # include # include diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 577d1012..73804fbf 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -6,7 +6,7 @@ #ifndef CLASS_WRAPPER_DWA20011221_HPP # define CLASS_WRAPPER_DWA20011221_HPP -# include +# include # include namespace boost { namespace python { namespace objects { @@ -15,7 +15,7 @@ template struct class_wrapper : to_python_converter > { - class_wrapper(ref const& type_) + class_wrapper(handle<> const& type_) : m_class_object_keeper(type_) { assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); @@ -34,7 +34,7 @@ struct class_wrapper // Everything's OK; Bypass NULL checks but guard against // exceptions. - ref result(raw_result, ref::allow_null()); + handle<> result(python::allow_null(raw_result)); // Build a value_holder to contain the object using the copy // constructor @@ -48,7 +48,7 @@ struct class_wrapper } private: - ref m_class_object_keeper; + handle<> m_class_object_keeper; static PyTypeObject* m_class_object; }; diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index 37f86e7d..ef2f1251 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include namespace boost { namespace python { namespace objects { @@ -27,7 +27,7 @@ struct BOOST_PYTHON_DECL function : PyObject // a function object (this class), and an existing function is // already there, add it as an overload. static void add_to_namespace( - ref const& name_space, char const* name, ref const& attribute); + handle<> const& name_space, char const* name, handle<> const& attribute); private: // helper functions void argument_error(PyObject* args, PyObject* keywords) const; diff --git a/include/boost/python/object/iterator.hpp b/include/boost/python/object/iterator.hpp index a237d5d7..7e801f92 100644 --- a/include/boost/python/object/iterator.hpp +++ b/include/boost/python/object/iterator.hpp @@ -11,7 +11,7 @@ # include # include # include -# include +# include # include # include # include @@ -42,9 +42,9 @@ struct default_iterator_call_policies template struct iterator_range { - iterator_range(ref sequence, Iterator start, Iterator finish); + iterator_range(handle<> sequence, Iterator start, Iterator finish); - ref m_sequence; // Keeps the sequence alive while iterating. + handle<> m_sequence; // Keeps the sequence alive while iterating. Iterator m_start; Iterator m_finish; }; @@ -113,18 +113,18 @@ namespace detail // policies, creating it if neccessary. Requires: NextPolicies is // default-constructible. template - ref demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies()) + handle<> demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies()) { typedef iterator_range range_; // Check the registry. If one is already registered, return it. - ref result( + handle<> result( objects::registered_class_object(python::type_id())); if (result.get() == 0) { // Make a callable object which can be used as the iterator's next() function. - ref next_function( + handle<> next_function( new objects::function( objects::py_function( bind(&detail::iterator_next::execute, _1, _2, policies)) @@ -174,7 +174,7 @@ namespace detail // Build and convert the iterator_range<>. return cr( iterator_range( - ref(arg0, ref::increment_count) + handle<>(python::borrow(arg0)) , get_start(x), get_finish(x))); } }; @@ -187,13 +187,13 @@ namespace detail // iterators for the range, and an instance of NextPolicies is used as // CallPolicies for the Python iterator's next() function. template -inline ref make_iterator_function( +inline handle<> make_iterator_function( Accessor1 const& get_start, Accessor2 const& get_finish , boost::type* = 0, NextPolicies* = 0) { typedef typename Accessor1::result_type result_type; - return ref( + return handle<>( new objects::function( objects::py_function( boost::bind( @@ -210,7 +210,7 @@ inline ref make_iterator_function( // template inline iterator_range::iterator_range( - ref sequence, Iterator start, Iterator finish) + handle<> sequence, Iterator start, Iterator finish) : m_sequence(sequence), m_start(start), m_finish(finish) { } diff --git a/include/boost/python/object/iterator_core.hpp b/include/boost/python/object/iterator_core.hpp index dee87050..c3d5f6ae 100644 --- a/include/boost/python/object/iterator_core.hpp +++ b/include/boost/python/object/iterator_core.hpp @@ -6,11 +6,11 @@ #ifndef ITERATOR_CORE_DWA2002512_HPP # define ITERATOR_CORE_DWA2002512_HPP -# include +# include namespace boost { namespace python { namespace objects { -BOOST_PYTHON_DECL ref identity_function(); +BOOST_PYTHON_DECL handle<> identity_function(); BOOST_PYTHON_DECL void set_stop_iteration_error(); }}} // namespace boost::python::object diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp index 8b230478..a5b87d88 100644 --- a/include/boost/python/objects.hpp +++ b/include/boost/python/objects.hpp @@ -9,11 +9,14 @@ #ifndef OBJECTS_DWA051100_H_ # define OBJECTS_DWA051100_H_ -# include -# include -# include -# include "boost/operators.hpp" -# include +# ifdef BOOST_PYTHON_V2 +# include +# else +# include +# include +# include +# include "boost/operators.hpp" +# include namespace boost { namespace python { @@ -354,8 +357,6 @@ struct BOOST_PYTHON_DECL list_slice_proxy }} // namespace boost::python -# ifndef BOOST_PYTHON_V2 - BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple&); @@ -391,5 +392,5 @@ inline boost::python::dictionary from_python(PyObject* p, boost::python::type +# include +# include +# include "boost/operators.hpp" +# include + +namespace boost { namespace python { + +class BOOST_PYTHON_DECL objects_base +{ + public: + explicit objects_base(handle<> const& p); + + // Return a reference to the held object + handle<> reference() const; + + // Return a raw pointer to the held object + PyObject* get() const; + + private: + handle<> m_p; +}; + +class tuple; + +class BOOST_PYTHON_DECL tuple_base : public objects_base +{ + public: + explicit tuple_base(std::size_t n = 0); + explicit tuple_base(handle<> p); + + static PyTypeObject* type_obj(); + static bool accepts(handle<> p); + std::size_t size() const; + handle<> operator[](std::size_t pos) const; + + void set_item(std::size_t pos, const handle<>& rhs); + + tuple slice(int low, int high) const; + + friend BOOST_PYTHON_DECL tuple operator+(const tuple&, const tuple&); + friend BOOST_PYTHON_DECL tuple& operator+=(tuple&, const tuple&); +}; + +class tuple : public tuple_base +{ + public: + explicit tuple(std::size_t n = 0) : tuple_base(n) {} + explicit tuple(handle<> p) : tuple_base(p) {} + + template + tuple(const std::pair& x) + : tuple_base(handle<>(PyTuple_New(2))) + { + set_item(0, x.first); + set_item(1, x.second); + } + + template + tuple(const First& first, const Second& second) + : tuple_base(handle<>(PyTuple_New(2))) + { + set_item(0, first); + set_item(1, second); + } + + template + tuple(const First& first, const Second& second, const Third& third) + : tuple_base(handle<>(PyTuple_New(3))) + { + set_item(0, first); + set_item(1, second); + set_item(2, third); + } + + template + tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth) + : tuple_base(handle<>(PyTuple_New(4))) + { + set_item(0, first); + set_item(1, second); + set_item(2, third); + set_item(3, fourth); + } + + void set_item(std::size_t pos, const handle<>& rhs) + { + tuple_base::set_item(pos, rhs); + } +}; + +class list; + +struct BOOST_PYTHON_DECL list_proxy; +struct BOOST_PYTHON_DECL list_slice_proxy; + +class BOOST_PYTHON_DECL list_base : public objects_base +{ + protected: + typedef list_proxy proxy; + typedef list_slice_proxy slice_proxy; + public: + explicit list_base(handle<> p); + explicit list_base(std::size_t sz = 0); + static PyTypeObject* type_obj(); + static bool accepts(handle<> p); + std::size_t size() const; + handle<> operator[](std::size_t pos) const; + proxy operator[](std::size_t pos); + handle<> get_item(std::size_t pos) const; + + void set_item(std::size_t pos, const handle<>& ); + +// void set_item(std::size_t pos, const object& ); + + void insert(std::size_t index, const handle<>& item); + + void push_back(const handle<>& item); + + void append(const handle<>& item); + + list slice(int low, int high) const; + slice_proxy slice(int low, int high); + void sort(); + void reverse(); + tuple as_tuple() const; +}; + +class list : public list_base +{ + public: + explicit list(handle<> p) : list_base(p) {} + explicit list(std::size_t sz = 0) : list_base(sz) {} + template + void set_item(std::size_t pos, const T& x) + { this->set_item(pos, make_ref(x)); } + template + void insert(std::size_t index, const T& x) + { this->insert(index, make_ref(x)); } + template + void push_back(const T& item) + { this->push_back(make_ref(item)); } + template + void append(const T& item) + { this->append(make_ref(item)); } + + void set_item(std::size_t pos, const handle<>& x) { list_base::set_item(pos, x); } + void insert(std::size_t index, const handle<>& item) { list_base::insert(index, item); } + void push_back(const handle<>& item) { list_base::push_back(item); } + void append(const handle<>& item) { list_base::append(item); } +}; + +class BOOST_PYTHON_DECL string + : public objects_base, public boost::multipliable2 +{ + public: + // Construct from an owned PyObject*. + // Precondition: p must point to a python string. + explicit string(handle<> p); + explicit string(const char* s); + string(const char* s, std::size_t length); + string(const string& rhs); + + enum interned_t { interned }; + string(const char* s, interned_t); + + // Get the type object for Strings + static PyTypeObject* type_obj(); + + // Return true if the given object is a python string + static bool accepts(handle<> o); + + // Return the length of the string. + std::size_t size() const; + + // Returns a null-terminated representation of the contents of string. + // The pointer refers to the internal buffer of string, not a copy. + // The data must not be modified in any way. It must not be de-allocated. + const char* c_str() const; + + string& operator*=(unsigned int repeat_count); + string& operator+=(const string& rhs); + friend string operator+(string x, string y); + string& operator+=(const char* rhs); + friend string operator+(string x, const char* y); + friend string operator+(const char* x, string y); + + void intern(); + + friend string operator%(const string& format, const tuple& args); +}; + +class dictionary; + +struct BOOST_PYTHON_DECL dictionary_proxy; + +class BOOST_PYTHON_DECL dictionary_base : public objects_base +{ + protected: + typedef dictionary_proxy proxy; + + public: + explicit dictionary_base(handle<> p); + dictionary_base(); + void clear(); + + static PyTypeObject* type_obj(); + static bool accepts(handle<> p); + + public: + proxy operator[](handle<> key); + handle<> operator[](handle<> key) const; + handle<> get_item(const handle<>& key) const; + handle<> get_item(const handle<>& key, const handle<>& default_) const; + + void set_item(const handle<>& key, const handle<>& value); + + void erase(handle<> key); + +// proxy operator[](const object& key); +// ref operator[](const object& key) const; + +// ref get_item(const object& key, ref default_ = ref()) const; +// void set_item(const object& key, const ref& value); + +// void erase(const object& key); + + list items() const; + list keys() const; + list values() const; + + std::size_t size() const; + // TODO: iterator support +}; + +struct BOOST_PYTHON_DECL dictionary_proxy +{ + template + const handle<>& operator=(const T& rhs) + { return (*this) = make_ref(rhs); } + const handle<>& operator=(const handle<>& rhs); + + operator handle<>() const; + private: + friend class dictionary_base; + dictionary_proxy(const handle<>& dict, const handle<>& key); + + // This is needed to work around the very strange MSVC error report that the + // return type of the built-in operator= differs from that of the ones + // defined above. Couldn't hurt to make these un-assignable anyway, though. + const handle<>& operator=(const dictionary_proxy&); // Not actually implemented + private: + handle<> m_dict; + handle<> m_key; +}; + +class dictionary : public dictionary_base +{ + typedef dictionary_proxy proxy; + public: + explicit dictionary(handle<> p) : dictionary_base(p) {} + dictionary() : dictionary_base() {} + + template + proxy operator[](const Key& key) + { return this->operator[](make_ref(key)); } + proxy operator[](handle<> key) + { return dictionary_base::operator[](key); } + + template + handle<> operator[](const Key& key) const + { return this->operator[](make_ref(key)); } + handle<> operator[](handle<> key) const + { return dictionary_base::operator[](key); } + + template + handle<> get_item(const Key& key) const + { return this->get_item(make_ref(key)); } + handle<> get_item(const handle<>& key) const + { return dictionary_base::get_item(key); } + + template + handle<> get_item(const Key& key, const Default& default_) const + { return this->get_item(make_ref(key), make_ref(default_)); } + handle<> get_item(const handle<>& key, const handle<>& default_) const + { return dictionary_base::get_item(key, default_); } + + template + void set_item(const Key& key, const Value& value) + { this->set_item(make_ref(key), make_ref(value)); } + void set_item(const handle<>& key, const handle<>& value) + { dictionary_base::set_item(key, value); } + + template + void erase(const Key& key) + { this->erase(make_ref(key)); } + void erase(handle<> key) + { dictionary_base::erase(key); } +}; + +struct BOOST_PYTHON_DECL list_proxy +{ + template + const handle<>& operator=(const T& rhs) + { return (*this) = make_ref(rhs); } + const handle<>& operator=(const handle<>& rhs); + + operator handle<>() const; + + private: + friend class list_base; + list_proxy(const handle<>& list, std::size_t index); + + // This is needed to work around the very strange MSVC error report that the + // return type of the built-in operator= differs from that of the ones + // defined above. Couldn't hurt to make these un-assignable anyway, though. + const handle<>& operator=(const list_proxy&); // Not actually implemented + private: + list m_list; + std::size_t m_index; +}; + +struct BOOST_PYTHON_DECL list_slice_proxy +{ + const list& operator=(const list& rhs); + operator handle<>() const; + operator list() const; + std::size_t size() const; + handle<> operator[](std::size_t pos) const; + private: + friend class list_base; + list_slice_proxy(const handle<>& list, int low, int high); + private: + handle<> m_list; + int m_low, m_high; +}; + +}} // namespace boost::python + +#endif // OBJECTS_DWA20020611_H diff --git a/include/boost/python/operators2.hpp b/include/boost/python/operators2.hpp index aa97071f..a58b7559 100755 --- a/include/boost/python/operators2.hpp +++ b/include/boost/python/operators2.hpp @@ -27,7 +27,7 @@ namespace detail template PyObject* convert_result(T const& x) { - return converter::arg_to_python(x).get_incref(); + return converter::arg_to_python(x).release(); } // Operator implementation template declarations. The nested apply diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index 97edef99..f070f114 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -9,6 +9,12 @@ #ifndef PYPTR_DWA050400_H_ # define PYPTR_DWA050400_H_ +# ifdef BOOST_PYTHON_V2 + +# error obsolete + +# else + # include # include # include @@ -19,7 +25,6 @@ # include # include -# ifndef BOOST_PYTHON_V2 # include BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -39,19 +44,14 @@ struct py_ptr_conversions : Base }; BOOST_PYTHON_END_CONVERSION_NAMESPACE -# endif namespace boost { namespace python { -# ifndef BOOST_PYTHON_V2 BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions); -# endif template class reference -# ifndef BOOST_PYTHON_V2 : public py_ptr_conversions, T> -# endif { public: typedef T value_type; @@ -215,12 +215,7 @@ private: inline PyObject* object() const { -#ifdef BOOST_PYTHON_V2 - return (PyObject*)( - (char*)&m_p->ob_type - offsetof(PyObject,ob_type)); -#else return as_object(m_p); -#endif } T* m_p; @@ -228,14 +223,14 @@ private: typedef reference ref; -#ifndef BOOST_PYTHON_V2 template ref make_ref(const T& x) { return ref(to_python(x)); } -#endif }} // namespace boost::python +#endif // BOOST_PYTHON_V2 + #endif // PYPTR_DWA050400_H_ diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index 480cd909..6aaa2ab0 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -107,7 +107,7 @@ inline PyObject* to_python_indirect::operator()(T x) const // Everything's OK; Bypass NULL checks but guard against // exceptions. - ref result(raw_result, ref::allow_null()); + handle<> result(python::allow_null(raw_result)); // Build a value_holder to contain the object using the copy // constructor diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index c495445d..038d0ff5 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -54,7 +54,7 @@ namespace { // Get the (intermediate) source object unaryfunc creator = *static_cast(data->convertible); - ref intermediate(creator(obj)); + handle<> intermediate(creator(obj)); // Get the location in which to construct void* storage = ((rvalue_base_data*)data)->storage.bytes; diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp index bd6aa904..573e38f9 100644 --- a/src/converter/callback.cpp +++ b/src/converter/callback.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace boost { namespace python { namespace converter { @@ -35,7 +35,7 @@ namespace detail arg_to_python_base::arg_to_python_base( void const volatile* source, to_python_function_t converter) - : arg_to_python_holder(convert(source, converter)) + : handle<>(convert(source, converter)) { } @@ -65,7 +65,7 @@ namespace detail PyObject* source , lvalue_from_python_registration*const& converters) { - ref holder(source); + handle<> holder(source); if (source->ob_refcnt <= 2) { PyErr_SetString( @@ -106,7 +106,7 @@ namespace detail BOOST_PYTHON_DECL void* convert_rvalue(PyObject* src, rvalue_stage1_data& data, void* storage) { - ref holder(src); + handle<> holder(src); data = find(src, static_cast(data.convertible)); diff --git a/src/errors.cpp b/src/errors.cpp index 6d0cfd90..cd188cb6 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -54,13 +54,6 @@ void BOOST_PYTHON_DECL throw_error_already_set() throw error_already_set(); } -BOOST_PYTHON_DECL PyObject* expect_non_null_impl(PyObject* x) -{ - if (x == 0) - throw_error_already_set(); - return x; -} - namespace detail { BOOST_PYTHON_DECL void expect_complex(PyObject* p) diff --git a/src/module.cpp b/src/module.cpp index e958c6d8..e5d996cc 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -8,13 +8,14 @@ #include #include +#include namespace boost { namespace python { namespace detail { module_base::module_base(const char* name) : m_module( - Py_InitModule(const_cast(name), initial_methods) - , ref::increment_count) + borrow(Py_InitModule(const_cast(name), initial_methods)) + ) { } @@ -24,38 +25,33 @@ module_base::~module_base() void module_base::setattr(const char* name, PyObject* x) { - setattr(name, ref(x)); + setattr(name, handle<>(x)); } -void module_base::setattr(char const* name, ref const& x) +void module_base::setattr(char const* name, handle<> const& x) { // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace(m_module, name, x); } -void module_base::add(PyTypeObject* x) +void module_base::add(type_handle const& x) { - this->setattr(x->tp_name, (PyObject*)x); + this->setattr(x->tp_name, x); } -void module_base::add_type(ref x) +void module_base::add_class(type_handle const& class_obj) { - assert(PyObject_TypeCheck(x.get(), &PyType_Type)); - add((PyTypeObject*)x.release()); -} - -void module_base::add_class(ref const& class_obj) -{ - this->add_type(class_obj); + this->add(class_obj); - ref module_name( + handle<> module_name( PyObject_GetAttrString( m_module.get(), const_cast("__name__")) ); int status = PyObject_SetAttrString( - class_obj.get(), const_cast("__module__"), module_name.get()); + python::upcast(class_obj.get()) + , const_cast("__module__"), module_name.get()); if (status == -1) throw_error_already_set(); diff --git a/src/object/class.cpp b/src/object/class.cpp index ea0c332b..cfea075f 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -101,16 +101,16 @@ void instance_holder::install(PyObject* self) throw() namespace objects { // Get the metatype object for all extension classes. - BOOST_PYTHON_DECL ref class_metatype() + BOOST_PYTHON_DECL type_handle class_metatype() { if (class_metatype_object.tp_dict == 0) { class_metatype_object.ob_type = &PyType_Type; class_metatype_object.tp_base = &PyType_Type; if (PyType_Ready(&class_metatype_object)) - return ref(); + return type_handle(); } - return ref((PyObject*)&class_metatype_object, ref::increment_count); + return type_handle(borrow(&class_metatype_object)); } extern "C" { @@ -172,16 +172,16 @@ namespace objects PyType_GenericNew }; - BOOST_PYTHON_DECL ref class_type() + BOOST_PYTHON_DECL type_handle class_type() { if (class_type_object.tp_dict == 0) { - class_type_object.ob_type = (PyTypeObject*)class_metatype().release(); + class_type_object.ob_type = incref(class_metatype().get()); class_type_object.tp_base = &PyBaseObject_Type; if (PyType_Ready(&class_type_object)) - return ref(); + return type_handle(); } - return ref((PyObject*)&class_type_object, ref::increment_count); + return type_handle(borrow(&class_type_object)); } BOOST_PYTHON_DECL void* @@ -206,11 +206,11 @@ namespace objects struct class_registry { public: - ref get(class_id id) const; - ref query(class_id id) const; - void set(class_id, ref class_object); + type_handle get(class_id id) const; + type_handle query(class_id id) const; + void set(class_id, type_handle class_object); private: - typedef detail::map_entry entry; + typedef detail::map_entry entry; std::vector m_impl; }; @@ -220,7 +220,7 @@ namespace objects return x; } - inline ref class_registry::query(class_id id) const + inline type_handle class_registry::query(class_id id) const { std::vector::const_iterator start = m_impl.begin(); std::vector::const_iterator finish = m_impl.end(); @@ -228,12 +228,12 @@ namespace objects std::vector::const_iterator p = boost::detail::lower_bound(start, finish, id); - return (p == finish || p->key != id) ? ref() : p->value; + return (p == finish || p->key != id) ? type_handle() : p->value; } - inline ref class_registry::get(class_id id) const + inline type_handle class_registry::get(class_id id) const { - ref result(this->query(id)); + type_handle result(this->query(id)); if (result.get() == 0) { @@ -245,7 +245,7 @@ namespace objects return result; } - inline void class_registry::set(class_id id, ref object) + inline void class_registry::set(class_id id, type_handle object) { std::vector::iterator start = m_impl.begin(); std::vector::iterator finish = m_impl.end(); @@ -276,8 +276,10 @@ namespace objects args.set_item(0, string(name).reference()); args.set_item(1, bases.reference()); args.set_item(2, dictionary().reference()); - - m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); + + PyObject* c = PyObject_CallObject(upcast(class_metatype().get()), args.get()); + assert(PyType_IsSubtype(c->ob_type, &PyType_Type)); + m_object = type_handle((PyTypeObject*)c); r.set(types[0], m_object); } @@ -287,25 +289,25 @@ namespace objects extern DL_IMPORT(PyTypeObject) PyProperty_Type; } - void class_base::add_property(char const* name, ref const& fget) + void class_base::add_property(char const* name, handle<> const& fget) { - ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.get())); + handle<> property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "O", fget.get())); setattr(name, property); } - void class_base::add_property(char const* name, ref const& fget, ref const& fset) + void class_base::add_property(char const* name, handle<> const& fget, handle<> const& fset) { - ref property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.get(), fset.get())); + handle<> property(PyObject_CallFunction((PyObject*)&PyProperty_Type, "OO", fget.get(), fset.get())); setattr(name, property); } - void class_base::setattr(char const* name, ref const& x) + void class_base::setattr(char const* name, handle<> const& x) { - if (PyObject_SetAttrString(object().get(), const_cast(name), x.get()) < 0) + if (PyObject_SetAttrString(upcast(object().get()), const_cast(name), x.get()) < 0) throw_error_already_set(); } - BOOST_PYTHON_DECL ref registered_class_object(class_id id) + BOOST_PYTHON_DECL type_handle registered_class_object(class_id id) { return registry().query(id); } diff --git a/src/object/function.cpp b/src/object/function.cpp index 0d89791c..8855ba75 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -149,14 +149,14 @@ namespace function* not_implemented_function() { static function* result = new function(py_function(¬_implemented_impl), 2, 3); - static ref keeper(result); + static handle<> keeper(result); return result; } } void function::add_to_namespace( - ref const& name_space, char const* name_, ref const& attribute) + handle<> const& name_space, char const* name_, handle<> const& attribute) { string const name(name_); PyObject* const ns = name_space.get(); @@ -175,7 +175,7 @@ void function::add_to_namespace( if (dict == 0) throw_error_already_set(); - ref existing(PyObject_GetItem(dict, name.get()), ref::null_ok); + handle<> existing( allow_null(PyObject_GetItem(dict, name.get())) ); if (existing.get()) { diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp index 6a927726..8b6da346 100644 --- a/src/object/iterator.cpp +++ b/src/object/iterator.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include namespace boost { namespace python { namespace objects { @@ -18,9 +18,9 @@ static PyObject* identity(PyObject* args_, PyObject*) return x; } -BOOST_PYTHON_DECL ref identity_function() +BOOST_PYTHON_DECL handle<> identity_function() { - static ref result(new objects::function(py_function(&identity), 1)); + static handle<> result(new objects::function(py_function(&identity), 1)); return result; } diff --git a/src/objects2.cpp b/src/objects2.cpp new file mode 100755 index 00000000..5ec410ab --- /dev/null +++ b/src/objects2.cpp @@ -0,0 +1,426 @@ +// (C) Copyright David Abrahams 2000. 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. +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +// TODO: Move inline implementations from objects.cpp here + +#ifndef BOOST_PYTHON_SOURCE +# define BOOST_PYTHON_SOURCE +#endif + +#include +#include + +namespace boost { namespace python { + +objects_base::objects_base(handle<> const& p) + : m_p(borrow(p.get())) // Do the null check here +{} + +// Return a reference to the held object +handle<> objects_base::reference() const +{ + return m_p; +} + +// Return a raw pointer to the held object +PyObject* objects_base::get() const +{ + return m_p.get(); +} + +}} // namespace boost::python + +namespace boost { namespace python { + +tuple_base::tuple_base(std::size_t n) + : objects_base(handle<>(PyTuple_New(n))) +{ + for (std::size_t i = 0; i < n; ++i) + PyTuple_SET_ITEM(get(), i, detail::none()); +} + +tuple_base::tuple_base(handle<> p) + : objects_base(p) +{ + assert(accepts(p)); + if (!accepts(p)) + { + PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); + throw_error_already_set(); + } +} + +PyTypeObject* tuple_base::type_obj() +{ + return &PyTuple_Type; +} + +bool tuple_base::accepts(handle<> p) +{ + return PyTuple_Check(p.get()); +} + +std::size_t tuple_base::size() const +{ + return PyTuple_Size(get()); +} + +handle<> tuple_base::operator[](std::size_t pos) const +{ + return handle<>(borrow(PyTuple_GetItem(get(), static_cast(pos)))); +} + +void tuple_base::set_item(std::size_t pos, const handle<>& rhs) +{ + int failed = PyTuple_SetItem( + get() + , static_cast(pos) + , incref(expect_non_null(rhs.get())) + ); + (void)failed; + assert(failed == 0); +} + +tuple tuple_base::slice(int low, int high) const +{ + return tuple(handle<>(PyTuple_GetSlice(get(), low, high))); +} + +BOOST_PYTHON_DECL tuple& operator+=(tuple& self, const tuple& rhs) +{ + return self = self + rhs; +} + + +// Construct from an owned PyObject*. +// Precondition: p must point to a python string. +string::string(handle<> p) + : objects_base(p) +{ + assert(accepts(p)); + if (!accepts(p)) + { + PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); + throw_error_already_set(); + } +} + +string::string(const char* s) + : objects_base(handle<>(PyString_FromString(s))) {} + +string::string(const char* s, std::size_t length) + : objects_base(handle<>(PyString_FromStringAndSize(s, length))) {} + +string::string(const char* s, interned_t) + : objects_base(handle<>(PyString_InternFromString(s))) {} + +string::string(const string& rhs) + : objects_base(rhs.reference()) {} + +// Get the type object for Strings +PyTypeObject* string::type_obj() +{ return &PyString_Type; } + +// Return true if the given object is a python string +bool string::accepts(handle<> o) +{ return PyString_Check(o.get()); } + +// Return the length of the string. +std::size_t string::size() const +{ + int size = PyString_GET_SIZE(get()); + assert(size >= 0); + return static_cast(size); +} + +// Returns a null-terminated representation of the contents of string. +// The pointer refers to the internal buffer of string, not a copy. +// The data must not be modified in any way. It must not be de-allocated. +const char* string::c_str() const +{ return PyString_AS_STRING(get()); } + +void string::intern() +{ // UNTESTED!! + *this = string(handle<>(borrow(PyString_InternFromString(c_str())))); +} + +string& string::operator*=(unsigned int repeat_count) +{ + *this = string(handle<>(PySequence_Repeat(get(), repeat_count))); + return *this; +} + +dictionary_base::dictionary_base(handle<> p) + : objects_base(p) +{ + assert(accepts(p)); + if (!accepts(p)) + { + PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); + throw_error_already_set(); + } +} + +dictionary_base::dictionary_base() + : objects_base(handle<>(PyDict_New())) {} + +PyTypeObject* dictionary_base::type_obj() +{ return &PyDict_Type; } + +bool dictionary_base::accepts(handle<> p) +{ return PyDict_Check(p.get()); } + +void dictionary_base::clear() +{ PyDict_Clear(get()); } + +const handle<>& dictionary_proxy::operator=(const handle<>& rhs) +{ + if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1) + throw_error_already_set(); + return rhs; +} + +dictionary_proxy::operator handle<>() const +{ + return handle<>( + m_dict->ob_type->tp_as_mapping->mp_subscript(m_dict.get(), m_key.get())); +} + +dictionary_proxy::dictionary_proxy(const handle<>& dict, const handle<>& key) + : m_dict(dict), m_key(key) {} + +dictionary_proxy dictionary_base::operator[](handle<> key) +{ return proxy(reference(), key); } + +handle<> dictionary_base::operator[](handle<> key) const { + // An odd MSVC bug causes the ".operator Ptr()" to be needed + return proxy(reference(), key).operator handle<>(); +} + + +handle<> dictionary_base::get_item(const handle<>& key) const +{ + return get_item(key, handle<>()); +} + +handle<> dictionary_base::get_item(const handle<>& key, const handle<>& default_) const +{ + PyObject* value_or_null = PyDict_GetItem(get(), key.get()); + if (value_or_null == 0 && !PyErr_Occurred()) + return default_; + else + return handle<>(borrow(value_or_null)); // Will throw if there was another error +} + +void dictionary_base::set_item(const handle<>& key, const handle<>& value) +{ + if (PyDict_SetItem(get(), key.get(), value.get()) == -1) + throw_error_already_set(); +} + +void dictionary_base::erase(handle<> key) { + if (PyDict_DelItem(get(), key.get()) == -1) + throw_error_already_set(); +} + +list dictionary_base::items() const { return list(handle<>(PyDict_Items(get()))); } +list dictionary_base::keys() const { return list(handle<>(PyDict_Keys(get()))); } +list dictionary_base::values() const { return list(handle<>(PyDict_Values(get()))); } + +std::size_t dictionary_base::size() const { return static_cast(PyDict_Size(get())); } + +string operator+(string x, string y) +{ + PyObject* io_string = incref(x.get()); + PyString_Concat(&io_string, y.get()); + return string(handle<>(io_string)); +} + +string& string::operator+=(const string& rhs) +{ + return *this = *this + rhs; +} + +string& string::operator+=(const char* y) +{ + return *this += string(y); +} + +string operator%(const string& format, const tuple& args) +{ + return string(handle<>(PyString_Format(format.get(), args.reference().get()))); +} + +string operator+(string x, const char* y) +{ + return x + string(y); +} + +string operator+(const char* x, string y) +{ + return string(x) + y; +} + +tuple operator+(const tuple& x, const tuple& y) +{ + tuple result(x.size() + y.size()); + for (std::size_t xi = 0; xi < x.size(); ++xi) + result.set_item(xi, x[xi]); + for (std::size_t yi = 0; yi < y.size(); ++yi) + result.set_item(yi + x.size(), y[yi]); + return result; +} + + +list_base::list_base(handle<> p) + : objects_base(p) +{ + assert(accepts(p)); + if (!accepts(p)) + { + PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name); + throw_error_already_set(); + } +} + +list_base::list_base(std::size_t sz) + : objects_base(handle<>(PyList_New(sz))) +{ +} + +PyTypeObject* list_base::type_obj() +{ + return &PyList_Type; +} + +bool list_base::accepts(handle<> p) +{ + return PyList_Check(p.get()); +} + +std::size_t list_base::size() const +{ + return PyList_Size(get()); +} + +handle<> list_base::operator[](std::size_t pos) const +{ + return handle<>(borrow(PyList_GetItem(get(), pos))); +} + +list_proxy list_base::operator[](std::size_t pos) +{ + return proxy(reference(), pos); +} + +void list_base::insert(std::size_t index, const handle<>& item) +{ + if (PyList_Insert(get(), index, item.get()) == -1) + throw_error_already_set(); +} + +void list_base::push_back(const handle<>& item) +{ + if (PyList_Append(get(), item.get()) == -1) + throw_error_already_set(); +} + +void list_base::append(const handle<>& item) +{ + this->push_back(item); +} + +list list_base::slice(int low, int high) const +{ + return list(handle<>(PyList_GetSlice(get(), low, high))); +} + +list_slice_proxy list_base::slice(int low, int high) +{ + return list_slice_proxy(reference(), low, high); +} + +void list_base::sort() +{ + if (PyList_Sort(get()) == -1) + throw_error_already_set(); +} + +void list_base::reverse() +{ + if (PyList_Reverse(get()) == -1) + throw_error_already_set(); +} + +tuple list_base::as_tuple() const +{ + return tuple(handle<>(PyList_AsTuple(get()))); +} + +const handle<>& list_proxy::operator=(const handle<>& rhs) +{ + m_list.set_item(m_index, rhs); + return rhs; +} + +list_proxy::operator handle<>() const +{ + return handle<>(borrow(PyList_GetItem(m_list.get(), m_index))); +} + +handle<> list_base::get_item(std::size_t pos) const +{ + return handle<>(borrow(PyList_GetItem(this->get(), pos))); +} + +void list_base::set_item(std::size_t pos, const handle<>& rhs) +{ + int result = PyList_SetItem(this->get(), pos, rhs.get()); + if (result == -1) + throw_error_already_set(); + Py_INCREF(rhs.get()); +} + +list_proxy::list_proxy(const handle<>& list, std::size_t index) + : m_list(list), m_index(index) +{ +} + +const list& list_slice_proxy::operator=(const list& rhs) +{ + if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1) + throw_error_already_set(); + return rhs; +} + +list_slice_proxy::operator handle<>() const +{ + return handle<>(PyList_GetSlice(m_list.get(), m_low, m_high)); +} + +list_slice_proxy::operator list() const +{ + return list(this->operator handle<>()); +} + +std::size_t list_slice_proxy::size() const +{ + return this->operator list().size(); +} + +handle<> list_slice_proxy::operator[](std::size_t pos) const +{ + return this->operator list()[pos].operator handle<>(); +} + +list_slice_proxy::list_slice_proxy(const handle<>& list, int low, int high) + : m_list(list), m_low(low), m_high(high) +{ +} + +}} // namespace boost::python diff --git a/test/Jamfile b/test/Jamfile index ef6c0b7d..c0459022 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -98,6 +98,10 @@ unit-test pointee unit-test result : result.cpp : $(BOOST_ROOT) ; +unit-test upcast + : upcast.cpp + : $(BOOST_ROOT) BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES) ; + unit-test select_holder : select_holder.cpp : $(BOOST_ROOT) BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES) diff --git a/test/cltree.cpp b/test/cltree.cpp index a17fd659..d99a4862 100755 --- a/test/cltree.cpp +++ b/test/cltree.cpp @@ -83,3 +83,6 @@ BOOST_PYTHON_MODULE_INIT(cltree) { ) ; } + +#include "module_tail.cpp" + diff --git a/test/upcast.cpp b/test/upcast.cpp new file mode 100755 index 00000000..b02d2534 --- /dev/null +++ b/test/upcast.cpp @@ -0,0 +1,19 @@ +// 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. +#include + +struct X { long x; }; +struct Y : X, PyObject {}; + +int main() +{ + PyTypeObject o; + Y y; + assert(&boost::python::upcast(&o)->ob_refcnt == &o.ob_refcnt); + assert(&boost::python::upcast(&y)->ob_refcnt == &y.ob_refcnt); + return 0; +} +