| 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 ARG_FROM_PYTHON_DWA2002127_HPP | 
|---|
| 6 | # define ARG_FROM_PYTHON_DWA2002127_HPP | 
|---|
| 7 |  | 
|---|
| 8 | # include <boost/python/detail/prefix.hpp> | 
|---|
| 9 | # include <boost/python/converter/from_python.hpp> | 
|---|
| 10 | # include <boost/python/detail/indirect_traits.hpp> | 
|---|
| 11 | # include <boost/type_traits/transform_traits.hpp> | 
|---|
| 12 | # include <boost/type_traits/cv_traits.hpp> | 
|---|
| 13 | # include <boost/python/converter/rvalue_from_python_data.hpp> | 
|---|
| 14 | # include <boost/mpl/eval_if.hpp> | 
|---|
| 15 | # include <boost/mpl/if.hpp> | 
|---|
| 16 | # include <boost/mpl/identity.hpp> | 
|---|
| 17 | # include <boost/mpl/and.hpp> | 
|---|
| 18 | # include <boost/mpl/or.hpp> | 
|---|
| 19 | # include <boost/mpl/not.hpp> | 
|---|
| 20 | # include <boost/python/converter/registry.hpp> | 
|---|
| 21 | # include <boost/python/converter/registered.hpp> | 
|---|
| 22 | # include <boost/python/converter/registered_pointee.hpp> | 
|---|
| 23 | # include <boost/python/detail/void_ptr.hpp> | 
|---|
| 24 | # include <boost/python/back_reference.hpp> | 
|---|
| 25 | # include <boost/python/detail/referent_storage.hpp> | 
|---|
| 26 | # include <boost/python/converter/obj_mgr_arg_from_python.hpp> | 
|---|
| 27 |  | 
|---|
| 28 | namespace boost { namespace python | 
|---|
| 29 | { | 
|---|
| 30 |   template <class T> struct arg_from_python; | 
|---|
| 31 | }} | 
|---|
| 32 |  | 
|---|
| 33 | // This header defines Python->C++ function argument converters, | 
|---|
| 34 | // parametrized on the argument type. | 
|---|
| 35 |  | 
|---|
| 36 | namespace boost { namespace python { namespace converter { | 
|---|
| 37 |  | 
|---|
| 38 | // | 
|---|
| 39 | // lvalue converters | 
|---|
| 40 | // | 
|---|
| 41 | //   These require that an lvalue of the type U is stored somewhere in | 
|---|
| 42 | //   the Python object being converted. | 
|---|
| 43 |  | 
|---|
| 44 | // Used when T == U*const& | 
|---|
| 45 | template <class T> | 
|---|
| 46 | struct pointer_cref_arg_from_python | 
|---|
| 47 | { | 
|---|
| 48 |     typedef T result_type; | 
|---|
| 49 |      | 
|---|
| 50 |     pointer_cref_arg_from_python(PyObject*); | 
|---|
| 51 |     T operator()() const; | 
|---|
| 52 |     bool convertible() const; | 
|---|
| 53 |      | 
|---|
| 54 |  private: // storage for a U* | 
|---|
| 55 |     // needed because not all compilers will let us declare U* as the | 
|---|
| 56 |     // return type of operator() -- we return U*const& instead | 
|---|
| 57 |     typename python::detail::referent_storage<T>::type m_result; | 
|---|
| 58 | }; | 
|---|
| 59 |  | 
|---|
| 60 | // Base class for pointer and reference converters | 
|---|
| 61 | struct arg_lvalue_from_python_base | 
|---|
| 62 | { | 
|---|
| 63 |  public: // member functions | 
|---|
| 64 |     arg_lvalue_from_python_base(void* result); | 
|---|
| 65 |     bool convertible() const; | 
|---|
| 66 |      | 
|---|
| 67 |  protected: // member functions | 
|---|
| 68 |     void*const& result() const; | 
|---|
| 69 |      | 
|---|
| 70 |  private: // data members | 
|---|
| 71 |     void* m_result; | 
|---|
| 72 | }; | 
|---|
| 73 |  | 
|---|
| 74 | // Used when T == U*  | 
|---|
| 75 | template <class T> | 
|---|
| 76 | struct pointer_arg_from_python : arg_lvalue_from_python_base | 
|---|
| 77 | { | 
|---|
| 78 |     typedef T result_type; | 
|---|
| 79 |      | 
|---|
| 80 |     pointer_arg_from_python(PyObject*); | 
|---|
| 81 |     T operator()() const; | 
|---|
| 82 | }; | 
|---|
| 83 |  | 
|---|
| 84 | // Used when T == U& and (T != V const& or T == W volatile&) | 
|---|
| 85 | template <class T> | 
|---|
| 86 | struct reference_arg_from_python : arg_lvalue_from_python_base | 
|---|
| 87 | { | 
|---|
| 88 |     typedef T result_type; | 
|---|
| 89 |      | 
|---|
| 90 |     reference_arg_from_python(PyObject*); | 
|---|
| 91 |     T operator()() const; | 
|---|
| 92 | }; | 
|---|
| 93 |  | 
|---|
| 94 | // =================== | 
|---|
| 95 |  | 
|---|
| 96 | // | 
|---|
| 97 | // rvalue converters | 
|---|
| 98 | // | 
|---|
| 99 | //   These require only that an object of type T can be created from | 
|---|
| 100 | //   the given Python object, but not that the T object exist | 
|---|
| 101 | //   somewhere in storage. | 
|---|
| 102 | // | 
|---|
| 103 |  | 
|---|
| 104 | // Used when T is a plain value (non-pointer, non-reference) type or | 
|---|
| 105 | // a (non-volatile) const reference to a plain value type. | 
|---|
| 106 | template <class T> | 
|---|
| 107 | struct arg_rvalue_from_python | 
|---|
| 108 | { | 
|---|
| 109 |     typedef typename boost::add_reference< | 
|---|
| 110 |         T | 
|---|
| 111 |         // We can't add_const here, or it would be impossible to pass | 
|---|
| 112 |         // auto_ptr<U> args from Python to C++ | 
|---|
| 113 |     >::type result_type; | 
|---|
| 114 |      | 
|---|
| 115 |     arg_rvalue_from_python(PyObject*); | 
|---|
| 116 |     bool convertible() const; | 
|---|
| 117 |  | 
|---|
| 118 | # if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196 | 
|---|
| 119 |     typename arg_rvalue_from_python<T>:: | 
|---|
| 120 | # endif  | 
|---|
| 121 |     result_type operator()(); | 
|---|
| 122 |      | 
|---|
| 123 |  private: | 
|---|
| 124 |     rvalue_from_python_data<result_type> m_data; | 
|---|
| 125 |     PyObject* m_source; | 
|---|
| 126 | }; | 
|---|
| 127 |  | 
|---|
| 128 |  | 
|---|
| 129 | // ================== | 
|---|
| 130 |  | 
|---|
| 131 | // Converts to a (PyObject*,T) bundle, for when you need a reference | 
|---|
| 132 | // back to the Python object | 
|---|
| 133 | template <class T> | 
|---|
| 134 | struct back_reference_arg_from_python | 
|---|
| 135 |     : boost::python::arg_from_python<typename T::type> | 
|---|
| 136 | { | 
|---|
| 137 |     typedef T result_type; | 
|---|
| 138 |      | 
|---|
| 139 |     back_reference_arg_from_python(PyObject*); | 
|---|
| 140 |     T operator()(); | 
|---|
| 141 |  private: | 
|---|
| 142 |     typedef boost::python::arg_from_python<typename T::type> base; | 
|---|
| 143 |     PyObject* m_source; | 
|---|
| 144 | }; | 
|---|
| 145 |  | 
|---|
| 146 |  | 
|---|
| 147 | // ================== | 
|---|
| 148 |  | 
|---|
| 149 | template <class C, class T, class F> | 
|---|
| 150 | struct if_2 | 
|---|
| 151 | { | 
|---|
| 152 |     typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type; | 
|---|
| 153 | }; | 
|---|
| 154 |  | 
|---|
| 155 | // This metafunction selects the appropriate arg_from_python converter | 
|---|
| 156 | // type for an argument of type T. | 
|---|
| 157 | template <class T> | 
|---|
| 158 | struct select_arg_from_python | 
|---|
| 159 | { | 
|---|
| 160 |     typedef typename if_2< | 
|---|
| 161 |         is_object_manager<T> | 
|---|
| 162 |       , object_manager_value_arg_from_python<T> | 
|---|
| 163 |       , if_2< | 
|---|
| 164 |             is_reference_to_object_manager<T> | 
|---|
| 165 |           , object_manager_ref_arg_from_python<T> | 
|---|
| 166 |           , if_2< | 
|---|
| 167 |                 is_pointer<T> | 
|---|
| 168 |               , pointer_arg_from_python<T> | 
|---|
| 169 |               , if_2< | 
|---|
| 170 |                     mpl::and_< | 
|---|
| 171 |                         indirect_traits::is_reference_to_pointer<T> | 
|---|
| 172 |                       , indirect_traits::is_reference_to_const<T> | 
|---|
| 173 |                       , mpl::not_<indirect_traits::is_reference_to_volatile<T> > | 
|---|
| 174 |                         > | 
|---|
| 175 |                   , pointer_cref_arg_from_python<T> | 
|---|
| 176 |                   , if_2< | 
|---|
| 177 |                         mpl::or_< | 
|---|
| 178 |                             indirect_traits::is_reference_to_non_const<T> | 
|---|
| 179 |                           , indirect_traits::is_reference_to_volatile<T> | 
|---|
| 180 |                         > | 
|---|
| 181 |                       , reference_arg_from_python<T> | 
|---|
| 182 |                       , mpl::if_< | 
|---|
| 183 |                             boost::python::is_back_reference<T> | 
|---|
| 184 |                           , back_reference_arg_from_python<T> | 
|---|
| 185 |                           , arg_rvalue_from_python<T> | 
|---|
| 186 |                         > | 
|---|
| 187 |                     > | 
|---|
| 188 |                 > | 
|---|
| 189 |             > | 
|---|
| 190 |         > | 
|---|
| 191 |     >::type type; | 
|---|
| 192 | }; | 
|---|
| 193 |  | 
|---|
| 194 | // ================== | 
|---|
| 195 |  | 
|---|
| 196 | // | 
|---|
| 197 | // implementations | 
|---|
| 198 | // | 
|---|
| 199 |  | 
|---|
| 200 | // arg_lvalue_from_python_base | 
|---|
| 201 | // | 
|---|
| 202 | inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result) | 
|---|
| 203 |     : m_result(result) | 
|---|
| 204 | { | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | inline bool arg_lvalue_from_python_base::convertible() const | 
|---|
| 208 | { | 
|---|
| 209 |     return m_result != 0; | 
|---|
| 210 | } | 
|---|
| 211 |  | 
|---|
| 212 | inline void*const& arg_lvalue_from_python_base::result() const | 
|---|
| 213 | { | 
|---|
| 214 |     return m_result; | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | // pointer_cref_arg_from_python | 
|---|
| 218 | // | 
|---|
| 219 | namespace detail | 
|---|
| 220 | { | 
|---|
| 221 |   // null_ptr_reference -- a function returning a reference to a null | 
|---|
| 222 |   // pointer of type U. Needed so that extractors for T*const& can | 
|---|
| 223 |   // convert Python's None. | 
|---|
| 224 |   template <class T> | 
|---|
| 225 |   struct null_ptr_owner | 
|---|
| 226 |   { | 
|---|
| 227 |       static T value; | 
|---|
| 228 |   }; | 
|---|
| 229 |   template <class T> T null_ptr_owner<T>::value = 0; | 
|---|
| 230 |    | 
|---|
| 231 |   template <class U> | 
|---|
| 232 |   inline U& null_ptr_reference(U&(*)()) | 
|---|
| 233 |   { | 
|---|
| 234 |       return null_ptr_owner<U>::value; | 
|---|
| 235 |   } | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|
| 238 | template <class T> | 
|---|
| 239 | inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p) | 
|---|
| 240 | { | 
|---|
| 241 |     // T == U*const&: store a U* in the m_result storage. Nonzero | 
|---|
| 242 |     // indicates success.  If find returns nonzero, it's a pointer to | 
|---|
| 243 |     // a U object. | 
|---|
| 244 |     python::detail::write_void_ptr_reference( | 
|---|
| 245 |         m_result.bytes | 
|---|
| 246 |         , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters) | 
|---|
| 247 |         , (T(*)())0); | 
|---|
| 248 | } | 
|---|
| 249 |  | 
|---|
| 250 | template <class T> | 
|---|
| 251 | inline bool pointer_cref_arg_from_python<T>::convertible() const | 
|---|
| 252 | { | 
|---|
| 253 |     return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; | 
|---|
| 254 | } | 
|---|
| 255 | template <class T> | 
|---|
| 256 | inline T pointer_cref_arg_from_python<T>::operator()() const | 
|---|
| 257 | { | 
|---|
| 258 |     return (*(void**)m_result.bytes == Py_None)  // None ==> 0 | 
|---|
| 259 |         ? detail::null_ptr_reference((T(*)())0) | 
|---|
| 260 |         // Otherwise, return a U*const& to the m_result storage. | 
|---|
| 261 |         : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); | 
|---|
| 262 | } | 
|---|
| 263 |  | 
|---|
| 264 | // pointer_arg_from_python | 
|---|
| 265 | // | 
|---|
| 266 | template <class T> | 
|---|
| 267 | inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p) | 
|---|
| 268 |     : arg_lvalue_from_python_base( | 
|---|
| 269 |         p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)) | 
|---|
| 270 | { | 
|---|
| 271 | } | 
|---|
| 272 |  | 
|---|
| 273 | template <class T> | 
|---|
| 274 | inline T pointer_arg_from_python<T>::operator()() const | 
|---|
| 275 | { | 
|---|
| 276 |     return (result() == Py_None) ? 0 : T(result()); | 
|---|
| 277 | } | 
|---|
| 278 |  | 
|---|
| 279 | // reference_arg_from_python | 
|---|
| 280 | // | 
|---|
| 281 | template <class T> | 
|---|
| 282 | inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p) | 
|---|
| 283 |     : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters)) | 
|---|
| 284 | { | 
|---|
| 285 | } | 
|---|
| 286 |  | 
|---|
| 287 | template <class T> | 
|---|
| 288 | inline T reference_arg_from_python<T>::operator()() const | 
|---|
| 289 | { | 
|---|
| 290 |     return python::detail::void_ptr_to_reference(result(), (T(*)())0); | 
|---|
| 291 | } | 
|---|
| 292 |  | 
|---|
| 293 |  | 
|---|
| 294 | // arg_rvalue_from_python | 
|---|
| 295 | // | 
|---|
| 296 | template <class T> | 
|---|
| 297 | inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj) | 
|---|
| 298 |     : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters)) | 
|---|
| 299 |     , m_source(obj) | 
|---|
| 300 | { | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | template <class T> | 
|---|
| 304 | inline bool arg_rvalue_from_python<T>::convertible() const | 
|---|
| 305 | { | 
|---|
| 306 |     return m_data.stage1.convertible != 0; | 
|---|
| 307 | } | 
|---|
| 308 |  | 
|---|
| 309 | template <class T> | 
|---|
| 310 | inline typename arg_rvalue_from_python<T>::result_type | 
|---|
| 311 | arg_rvalue_from_python<T>::operator()() | 
|---|
| 312 | { | 
|---|
| 313 |     if (m_data.stage1.construct != 0) | 
|---|
| 314 |         m_data.stage1.construct(m_source, &m_data.stage1); | 
|---|
| 315 |      | 
|---|
| 316 |     return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); | 
|---|
| 317 | } | 
|---|
| 318 |  | 
|---|
| 319 | // back_reference_arg_from_python | 
|---|
| 320 | // | 
|---|
| 321 | template <class T> | 
|---|
| 322 | back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x) | 
|---|
| 323 |   : base(x), m_source(x) | 
|---|
| 324 | { | 
|---|
| 325 | } | 
|---|
| 326 |  | 
|---|
| 327 | template <class T> | 
|---|
| 328 | inline T | 
|---|
| 329 | back_reference_arg_from_python<T>::operator()() | 
|---|
| 330 | { | 
|---|
| 331 |     return T(m_source, base::operator()()); | 
|---|
| 332 | } | 
|---|
| 333 |  | 
|---|
| 334 | }}} // namespace boost::python::converter | 
|---|
| 335 |  | 
|---|
| 336 | #endif // ARG_FROM_PYTHON_DWA2002127_HPP | 
|---|