diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 1a5890c6..2e59189e 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -47,14 +47,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*, handle<> const& obj, T* = 0) + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, object 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*, handle<> const&, T* = 0) + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, object const&, T* = 0) { } } @@ -104,11 +104,13 @@ class class_ : public objects::class_base // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace( - this->object(), name, - handle<>(detail::wrap_function( + *this, name + , object( + detail::new_reference( + 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) - ))); + )))); return *this; } @@ -132,8 +134,10 @@ class class_ : public objects::class_base // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace( - this->object(), op.name(), - handle<>(detail::wrap_function(&op_t::template apply::execute))); + *this, op.name() + , object( + detail::new_reference( + detail::wrap_function(&op_t::template apply::execute)))); return *this; } @@ -255,7 +259,7 @@ inline class_::class_() detail::register_copy_constructor( mpl::bool_t() , objects::select_holder((held_type*)0).get() - , this->object()); + , *this); } template @@ -268,7 +272,7 @@ inline class_::class_(char const* name) detail::register_copy_constructor( mpl::bool_t() , objects::select_holder((held_type*)0).get() - , this->object()); + , *this); } diff --git a/include/boost/python/iterator.hpp b/include/boost/python/iterator.hpp index 724b926a..673d26e6 100644 --- a/include/boost/python/iterator.hpp +++ b/include/boost/python/iterator.hpp @@ -8,6 +8,7 @@ # include # include +# include # include # include @@ -19,7 +20,7 @@ namespace detail // objects::make_iterator(...), which allows us to pass member // function and member data pointers. template - inline handle<> make_iterator( + inline object make_iterator( Accessor1 get_start, Accessor2 get_finish, boost::type* target = 0, NextPolicies* = 0) { return objects::make_iterator_function( @@ -70,9 +71,14 @@ struct iterators template handle<> range(Accessor1 start, Accessor2 finish) { - return detail::make_iterator( - start, finish - , detail::target(start)); + return handle<>( + borrowed(allow_null( + detail::make_iterator( + start, finish + , detail::target(start)) + .ptr() + )) + ); } // Create an iterator-building function which uses the given accessors @@ -80,7 +86,12 @@ handle<> range(Accessor1 start, Accessor2 finish) template handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) { - return detail::make_iterator(start, finish, detail::target(start)); + return handle<>( + borrowed( + allow_null( + detail::make_iterator(start, finish, detail::target(start)) + .ptr() + ))); } // Create an iterator-building function which uses the given accessors @@ -89,7 +100,12 @@ template handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type* = 0) { typedef typename add_reference::type target; - return detail::make_iterator(start, finish); + return handle<>( + borrowed( + allow_null( + detail::make_iterator(start, finish) + .ptr() + ))); } // A Python callable object which produces an iterator traversing diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 7a774496..25f8cf05 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -32,7 +32,7 @@ class module : public detail::module_base template module& add(class_ const& c) { - this->add_class(c.object()); + this->add_class(type_handle(borrowed((PyTypeObject*)c.ptr()))); return *this; } diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 8a686505..babd409a 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -12,6 +12,7 @@ # include # include # include +# include # include namespace boost { namespace python { @@ -23,7 +24,7 @@ namespace objects { // To identify a class, we don't need cv/reference decorations typedef type_info class_id; -struct BOOST_PYTHON_DECL class_base : private noncopyable +struct BOOST_PYTHON_DECL class_base : python::api::object { // constructor class_base( @@ -35,13 +36,10 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable ); // Retrieve the underlying object - 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&); void enable_pickling(bool getstate_manages_dict); - private: - type_handle m_object; }; BOOST_PYTHON_DECL type_handle registered_class_object(class_id id); diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 73804fbf..2e06f921 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -15,11 +15,11 @@ template struct class_wrapper : to_python_converter > { - class_wrapper(handle<> const& type_) + class_wrapper(object const& type_) : m_class_object_keeper(type_) { - assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); - m_class_object = (PyTypeObject*)type_.get(); + assert(type_.ptr()->ob_type == (PyTypeObject*)class_metatype().get()); + m_class_object = (PyTypeObject*)type_.ptr(); } static PyObject* convert(T const& x) @@ -48,7 +48,7 @@ struct class_wrapper } private: - handle<> m_class_object_keeper; + object 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 ef2f1251..ebd2a8c3 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -10,6 +10,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -27,7 +28,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( - handle<> const& name_space, char const* name, handle<> const& attribute); + object const& name_space, char const* name, object 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 c9434a4f..124759d6 100644 --- a/include/boost/python/object/iterator.hpp +++ b/include/boost/python/object/iterator.hpp @@ -17,6 +17,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -113,30 +114,28 @@ namespace detail // policies, creating it if neccessary. Requires: NextPolicies is // default-constructible. template - handle<> demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies()) + object 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. - handle<> result( + handle<> class_obj( 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. - handle<> next_function( - new objects::function( - objects::py_function( - bind(&detail::iterator_next::execute, _1, _2, policies)) - , 1)); - - result = class_(name) - .def("__iter__", identity_function()) - .setattr("next", next_function) - .object(); + if (class_obj.get() != 0) + return object(class_obj); - } - return result; + // Make a callable object which can be used as the iterator's next() function. + handle<> next_function( + new objects::function( + objects::py_function( + bind(&detail::iterator_next::execute, _1, _2, policies)) + , 1)); + + return class_(name) + .def("__iter__", identity_function()) + .setattr("next", next_function) + ; } // This class template acts as a generator for an ordinary function @@ -187,22 +186,23 @@ namespace detail // iterators for the range, and an instance of NextPolicies is used as // CallPolicies for the Python iterator's next() function. template -inline handle<> make_iterator_function( +inline object make_iterator_function( Accessor1 const& get_start, Accessor2 const& get_finish , boost::type* = 0, NextPolicies* = 0) { typedef typename Accessor1::result_type result_type; - return handle<>( - new objects::function( - objects::py_function( - boost::bind( - &detail::make_iterator_help< - Target,result_type,Accessor1,Accessor2,NextPolicies - >::create - , get_start, get_finish, _1, _2) - ) - ,1 )); + return object( + python::detail::new_non_null_reference( + new objects::function( + objects::py_function( + boost::bind( + &detail::make_iterator_help< + Target,result_type,Accessor1,Accessor2,NextPolicies + >::create + , get_start, get_finish, _1, _2)) + ,1 )) + ); } // diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 72cecdfc..8498a8df 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -11,7 +11,7 @@ # include -# include +# include # include # include # include diff --git a/include/boost/python/object_fwd.hpp b/include/boost/python/object_fwd.hpp new file mode 100644 index 00000000..8b0c093e --- /dev/null +++ b/include/boost/python/object_fwd.hpp @@ -0,0 +1,17 @@ +// 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 OBJECT_FWD_DWA2002724_HPP +# define OBJECT_FWD_DWA2002724_HPP + +namespace boost { namespace python { +namespace api +{ + class object; +} +using api::object; +}} // namespace boost::python + +#endif // OBJECT_FWD_DWA2002724_HPP diff --git a/src/module.cpp b/src/module.cpp index dcb64397..4a30f6f0 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -37,7 +37,7 @@ 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); + objects::function::add_to_namespace(python::object(m_module), name, python::object(x)); } void module_base::add(type_handle const& x) diff --git a/src/object/class.cpp b/src/object/class.cpp index 8b37752d..def44c33 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -243,9 +243,12 @@ namespace objects // corresponding to the class being created, and the // rest corresponding to its declared bases. // - class_base::class_base( - char const* name, std::size_t num_types, class_id const* const types) + + namespace { + inline object + new_class(char const* name, std::size_t num_types, class_id const* const types) + { assert(num_types >= 1); // Build a tuple of the base Python type objects. If no bases @@ -271,14 +274,20 @@ namespace objects // Call the class metatype to create a new class PyObject* c = PyObject_CallObject(upcast(class_metatype().get()), args.get()); assert(PyType_IsSubtype(c->ob_type, &PyType_Type)); - m_object = type_handle((PyTypeObject*)c); - + return object(python::detail::new_reference(c)); + } + } + + class_base::class_base( + char const* name, std::size_t num_types, class_id const* const types) + : object(new_class(name, num_types, types)) + { // Insert the new class object in the registry converter::registration& converters = const_cast( converter::registry::lookup(types[0])); // Class object is leaked, for now - converters.class_object = (PyTypeObject*)incref(m_object.get()); + converters.class_object = (PyTypeObject*)incref(this->ptr()); } extern "C" @@ -301,7 +310,7 @@ namespace objects void class_base::setattr(char const* name, handle<> const& x) { - if (PyObject_SetAttrString(upcast(object().get()), const_cast(name), x.get()) < 0) + if (PyObject_SetAttrString(this->ptr(), const_cast(name), x.get()) < 0) throw_error_already_set(); } @@ -317,7 +326,7 @@ namespace objects BOOST_PYTHON_DECL type_handle registered_class_object(class_id id) { - return objects::query_class(id); + return query_class(id); } } // namespace objects diff --git a/src/object/function.cpp b/src/object/function.cpp index 4fc6a141..dad36dd5 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -156,12 +156,12 @@ namespace } void function::add_to_namespace( - handle<> const& name_space, char const* name_, handle<> const& attribute) + object const& name_space, char const* name_, object const& attribute) { str const name(name_); - PyObject* const ns = name_space.get(); + PyObject* const ns = name_space.ptr(); - if (attribute->ob_type == &function_type) + if (attribute.ptr()->ob_type == &function_type) { PyObject* dict = 0; @@ -175,27 +175,27 @@ void function::add_to_namespace( if (dict == 0) throw_error_already_set(); - handle<> existing( allow_null(PyObject_GetItem(dict, name.ptr())) ); + handle<> existing( allow_null(::PyObject_GetItem(dict, name.ptr())) ); if (existing.get()) { if (existing->ob_type == &function_type) { - static_cast(attribute.get())->add_overload( + static_cast(attribute.ptr())->add_overload( static_cast(existing.get())); } } // Binary operators need an additional overload which returns NotImplemented else if (is_binary_operator(name_)) { - static_cast(attribute.get())->add_overload( + static_cast(attribute.ptr())->add_overload( not_implemented_function()); } } // The PyObject_GetAttrString() call above left an active error PyErr_Clear(); - if (PyObject_SetAttr(ns, name.ptr(), attribute.get()) < 0) + if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) throw_error_already_set(); } diff --git a/test/extract.cpp b/test/extract.cpp index 584eb60a..59e7e120 100644 --- a/test/extract.cpp +++ b/test/extract.cpp @@ -120,9 +120,7 @@ BOOST_PYTHON_MODULE_INIT(extract_ext) ; // Instantiate an X object through the Python interface - type_handle xc1 = x_class.object(); - object X_(xc1); - object x_obj = X_(3); + object x_obj = x_class(3); // Get the C++ object out of the Python object X const& x = extract(x_obj);