• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MANAGER_DWA2002614_HPP
6 # define OBJECT_MANAGER_DWA2002614_HPP
7 
8 # include <boost/python/handle.hpp>
9 # include <boost/python/cast.hpp>
10 # include <boost/python/converter/pyobject_traits.hpp>
11 # include <boost/python/detail/type_traits.hpp>
12 # include <boost/mpl/if.hpp>
13 # include <boost/python/detail/indirect_traits.hpp>
14 # include <boost/mpl/bool.hpp>
15 
16 // Facilities for dealing with types which always manage Python
17 // objects. Some examples are object, list, str, et. al. Different
18 // to_python/from_python conversion rules apply here because in
19 // contrast to other types which are typically embedded inside a
20 // Python object, these are wrapped around a Python object. For most
21 // object managers T, a C++ non-const T reference argument does not
22 // imply the existence of a T lvalue embedded in the corresponding
23 // Python argument, since mutating member functions on T actually only
24 // modify the held Python object.
25 //
26 // handle<T> is an object manager, though strictly speaking it should
27 // not be. In other words, even though mutating member functions of
28 // hanlde<T> actually modify the handle<T> and not the T object,
29 // handle<T>& arguments of wrapped functions will bind to "rvalues"
30 // wrapping the actual Python argument, just as with other object
31 // manager classes. Making an exception for handle<T> is simply not
32 // worth the trouble.
33 //
34 // borrowed<T> cv* is an object manager so that we can use the general
35 // to_python mechanisms to convert raw Python object pointers to
36 // python, without the usual semantic problems of using raw pointers.
37 
38 
39 // Object Manager Concept requirements:
40 //
41 //    T is an Object Manager
42 //    p is a PyObject*
43 //    x is a T
44 //
45 //    * object_manager_traits<T>::is_specialized == true
46 //
47 //    * T(detail::borrowed_reference(p))
48 //        Manages p without checking its type
49 //
50 //    * get_managed_object(x, boost::python::tag)
51 //        Convertible to PyObject*
52 //
53 // Additional requirements if T can be converted from_python:
54 //
55 //    * T(object_manager_traits<T>::adopt(p))
56 //        steals a reference to p, or throws a TypeError exception if
57 //        p doesn't have an appropriate type. May assume p is non-null
58 //
59 //    * X::check(p)
60 //        convertible to bool. True iff T(X::construct(p)) will not
61 //        throw.
62 
63 // Forward declarations
64 //
65 namespace boost { namespace python
66 {
67   namespace api
68   {
69     class object;
70   }
71 }}
72 
73 namespace boost { namespace python { namespace converter {
74 
75 
76 // Specializations for handle<T>
77 template <class T>
78 struct handle_object_manager_traits
79     : pyobject_traits<typename T::element_type>
80 {
81  private:
82   typedef pyobject_traits<typename T::element_type> base;
83 
84  public:
85   BOOST_STATIC_CONSTANT(bool, is_specialized = true);
86 
87   // Initialize with a null_ok pointer for efficiency, bypassing the
88   // null check since the source is always non-null.
adoptboost::python::converter::handle_object_manager_traits89   static null_ok<typename T::element_type>* adopt(PyObject* p)
90   {
91       return python::allow_null(base::checked_downcast(p));
92   }
93 };
94 
95 template <class T>
96 struct default_object_manager_traits
97 {
98     BOOST_STATIC_CONSTANT(
99         bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
100         );
101 };
102 
103 template <class T>
104 struct object_manager_traits
105     : mpl::if_c<
106          is_handle<T>::value
107        , handle_object_manager_traits<T>
108        , default_object_manager_traits<T>
109     >::type
110 {
111 };
112 
113 //
114 // Traits for detecting whether a type is an object manager or a
115 // (cv-qualified) reference to an object manager.
116 //
117 
118 template <class T>
119 struct is_object_manager
120     : mpl::bool_<object_manager_traits<T>::is_specialized>
121 {
122 };
123 
124 template <class T>
125 struct is_reference_to_object_manager
126     : mpl::false_
127 {
128 };
129 
130 template <class T>
131 struct is_reference_to_object_manager<T&>
132     : is_object_manager<T>
133 {
134 };
135 
136 template <class T>
137 struct is_reference_to_object_manager<T const&>
138     : is_object_manager<T>
139 {
140 };
141 
142 template <class T>
143 struct is_reference_to_object_manager<T volatile&>
144     : is_object_manager<T>
145 {
146 };
147 
148 template <class T>
149 struct is_reference_to_object_manager<T const volatile&>
150     : is_object_manager<T>
151 {
152 };
153 
154 }}} // namespace boost::python::converter
155 
156 #endif // OBJECT_MANAGER_DWA2002614_HPP
157