1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef OBJECT_CORE_DWA2002615_HPP
6 # define OBJECT_CORE_DWA2002615_HPP
8 # define BOOST_PYTHON_OBJECT_HAS_IS_NONE // added 2010-03-15 by rwgk
10 # include <boost/python/detail/prefix.hpp>
12 # include <boost/type.hpp>
14 # include <boost/python/call.hpp>
15 # include <boost/python/handle_fwd.hpp>
16 # include <boost/python/errors.hpp>
17 # include <boost/python/refcount.hpp>
18 # include <boost/python/detail/preprocessor.hpp>
19 # include <boost/python/tag.hpp>
20 # include <boost/python/def_visitor.hpp>
22 # include <boost/python/detail/raw_pyobject.hpp>
23 # include <boost/python/detail/dependent.hpp>
25 # include <boost/python/object/forward.hpp>
26 # include <boost/python/object/add_to_namespace.hpp>
28 # include <boost/preprocessor/iterate.hpp>
29 # include <boost/preprocessor/debug/line.hpp>
31 # include <boost/python/detail/is_xxx.hpp>
32 # include <boost/python/detail/string_literal.hpp>
33 # include <boost/python/detail/def_helper_fwd.hpp>
35 # include <boost/type_traits/is_same.hpp>
36 # include <boost/type_traits/is_convertible.hpp>
37 # include <boost/type_traits/remove_reference.hpp>
39 namespace boost { namespace python {
49 template <class T> struct arg_to_python;
52 // Put this in an inner namespace so that the generalized operators won't take over
56 // This file contains the definition of the object class and enough to
57 // construct/copy it, but not enough to do operations like
58 // attribute/item access or addition.
60 template <class Policies> class proxy;
62 struct const_attribute_policies;
63 struct attribute_policies;
64 struct const_objattribute_policies;
65 struct objattribute_policies;
66 struct const_item_policies;
68 struct const_slice_policies;
69 struct slice_policies;
72 typedef proxy<const_attribute_policies> const_object_attribute;
73 typedef proxy<attribute_policies> object_attribute;
74 typedef proxy<const_objattribute_policies> const_object_objattribute;
75 typedef proxy<objattribute_policies> object_objattribute;
76 typedef proxy<const_item_policies> const_object_item;
77 typedef proxy<item_policies> object_item;
78 typedef proxy<const_slice_policies> const_object_slice;
79 typedef proxy<slice_policies> object_slice;
82 // is_proxy -- proxy type detection
84 BOOST_PYTHON_IS_XXX_DEF(proxy, boost::python::api::proxy, 1)
86 template <class T> struct object_initializer;
89 typedef PyObject* (object::*bool_type)() const;
92 class object_operators : public def_visitor<U>
95 typedef object const& object_cref;
99 object operator()() const;
101 # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
102 # include BOOST_PP_ITERATE()
104 detail::args_proxy operator* () const;
105 object operator()(detail::args_proxy const &args) const;
106 object operator()(detail::args_proxy const &args,
107 detail::kwds_proxy const &kwds) const;
109 // truth value testing
111 operator bool_type() const;
112 bool operator!() const; // needed for vc6
116 const_object_attribute attr(char const*) const;
117 object_attribute attr(char const*);
118 const_object_objattribute attr(object const&) const;
119 object_objattribute attr(object const&);
121 // Wrap 'in' operator (aka. __contains__)
123 object contains(T const& key) const;
127 const_object_item operator[](object_cref) const;
128 object_item operator[](object_cref);
132 operator[](T const& key) const;
136 operator[](T const& key);
140 const_object_slice slice(object_cref, object_cref) const;
141 object_slice slice(object_cref, object_cref);
143 const_object_slice slice(slice_nil, object_cref) const;
144 object_slice slice(slice_nil, object_cref);
146 const_object_slice slice(object_cref, slice_nil) const;
147 object_slice slice(object_cref, slice_nil);
149 const_object_slice slice(slice_nil, slice_nil) const;
150 object_slice slice(slice_nil, slice_nil);
152 template <class T, class V>
154 slice(T const& start, V const& end) const;
156 template <class T, class V>
158 slice(T const& start, V const& end);
160 private: // def visitation for adding callable objects as class methods
162 template <class ClassT, class DocStringT>
163 void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const
165 // It's too late to specify anything other than docstrings if
166 // the callable object is already wrapped.
168 (is_same<char const*,DocStringT>::value
169 || detail::is_string_literal<DocStringT const>::value));
171 objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
174 friend class python::def_visitor_access;
177 // there is a confirmed CWPro8 codegen bug here. We prevent the
178 // early destruction of a temporary by binding a named object
180 # if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3003
181 typedef object const& object_cref2;
183 typedef object const object_cref2;
188 // VC6 and VC7 require this base class in order to generate the
189 // correct copy constructor for object. We can't define it there
190 // explicitly or it will complain of ambiguity.
191 struct object_base : object_operators<object>
193 // copy constructor without NULL checking, for efficiency.
194 inline object_base(object_base const&);
195 inline object_base(PyObject* ptr);
197 inline object_base& operator=(object_base const& rhs);
198 inline ~object_base();
200 // Underlying object access -- returns a borrowed reference
201 inline PyObject* ptr() const;
203 inline bool is_none() const;
209 template <class T, class U>
212 typename remove_reference<T>::type*
218 typename objects::unforward_cref<T>::type do_unforward_cref(T const& x)
226 PyObject* object_base_initializer(T const& x)
228 typedef typename is_derived<
229 BOOST_DEDUCED_TYPENAME objects::unforward_cref<T>::type
233 return object_initializer<
234 BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
241 class object : public object_base
244 // default constructor creates a None object
247 // explicit conversion from any C++ object to Python
249 explicit object(T const& x)
250 : object_base(object_base_initializer(x))
254 // Throw error_already_set() if the handle is null.
255 BOOST_PYTHON_DECL explicit object(handle<> const&);
258 public: // implementation detail -- for internal use only
259 explicit object(detail::borrowed_reference);
260 explicit object(detail::new_reference);
261 explicit object(detail::new_non_null_reference);
264 // Macros for forwarding constructors in classes derived from
265 // object. Derived classes will usually want these as an
266 // implementation detail
267 # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived, base) \
268 inline explicit derived(::boost::python::detail::borrowed_reference p) \
270 inline explicit derived(::boost::python::detail::new_reference p) \
272 inline explicit derived(::boost::python::detail::new_non_null_reference p) \
276 // object_initializer -- get the handle to construct the object with,
277 // based on whether T is a proxy or derived from object
279 template <bool is_proxy = false, bool is_object_manager = false>
280 struct object_initializer_impl
283 get(object const& x, mpl::true_)
285 return python::incref(x.ptr());
290 get(T const& x, mpl::false_)
292 return python::incref(converter::arg_to_python<T>(x).get());
297 struct object_initializer_impl<true, false>
299 template <class Policies>
301 get(proxy<Policies> const& x, mpl::false_)
303 return python::incref(x.operator object().ptr());
308 struct object_initializer_impl<false, true>
310 template <class T, class U>
314 return python::incref(get_managed_object(x, boost::python::tag));
319 struct object_initializer_impl<true, true>
320 {}; // empty implementation should cause an error
323 struct object_initializer : object_initializer_impl<
325 , converter::is_object_manager<T>::value
331 template <class T> struct extract;
343 call_proxy(object target) : m_target(target) {}
344 operator object() const { return m_target;}
350 class kwds_proxy : public call_proxy
353 kwds_proxy(object o = object()) : call_proxy(o) {}
355 class args_proxy : public call_proxy
358 args_proxy(object o) : call_proxy(o) {}
359 kwds_proxy operator* () const { return kwds_proxy(*this);}
363 template <typename U>
364 detail::args_proxy api::object_operators<U>::operator* () const
366 object_cref2 x = *static_cast<U const*>(this);
367 return boost::python::detail::args_proxy(x);
370 template <typename U>
371 object api::object_operators<U>::operator()(detail::args_proxy const &args) const
373 U const& self = *static_cast<U const*>(this);
374 PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
375 args.operator object().ptr(),
377 return object(boost::python::detail::new_reference(result));
381 template <typename U>
382 object api::object_operators<U>::operator()(detail::args_proxy const &args,
383 detail::kwds_proxy const &kwds) const
385 U const& self = *static_cast<U const*>(this);
386 PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
387 args.operator object().ptr(),
388 kwds.operator object().ptr());
389 return object(boost::python::detail::new_reference(result));
394 template <typename U>
396 object api::object_operators<U>::contains(T const& key) const
398 return this->attr("__contains__")(object(key));
402 inline object::object()
403 : object_base(python::incref(Py_None))
406 // copy constructor without NULL checking, for efficiency
407 inline api::object_base::object_base(object_base const& rhs)
408 : m_ptr(python::incref(rhs.m_ptr))
411 inline api::object_base::object_base(PyObject* p)
415 inline api::object_base& api::object_base::operator=(api::object_base const& rhs)
417 Py_INCREF(rhs.m_ptr);
418 Py_DECREF(this->m_ptr);
419 this->m_ptr = rhs.m_ptr;
423 inline api::object_base::~object_base()
425 assert( Py_REFCNT(m_ptr) > 0 );
429 inline object::object(detail::borrowed_reference p)
430 : object_base(python::incref((PyObject*)p))
433 inline object::object(detail::new_reference p)
434 : object_base(expect_non_null((PyObject*)p))
437 inline object::object(detail::new_non_null_reference p)
438 : object_base((PyObject*)p)
441 inline PyObject* api::object_base::ptr() const
446 inline bool api::object_base::is_none() const
448 return (m_ptr == Py_None);
452 // Converter specialization implementations
456 template <class T> struct object_manager_traits;
459 struct object_manager_traits<object>
461 BOOST_STATIC_CONSTANT(bool, is_specialized = true);
462 static bool check(PyObject*) { return true; }
464 static python::detail::new_non_null_reference adopt(PyObject* x)
466 return python::detail::new_non_null_reference(x);
468 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
469 static PyTypeObject const *get_pytype() {return 0;}
474 inline PyObject* get_managed_object(object const& x, tag_t)
479 }} // namespace boost::python
481 # include <boost/python/slice_nil.hpp>
483 #endif // OBJECT_CORE_DWA2002615_HPP