Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:37

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef ARG_FROM_PYTHON_DWA2002127_HPP
0006 # define ARG_FROM_PYTHON_DWA2002127_HPP
0007 
0008 # include <boost/python/detail/prefix.hpp>
0009 # include <boost/python/converter/from_python.hpp>
0010 # include <boost/python/detail/indirect_traits.hpp>
0011 # include <boost/python/detail/type_traits.hpp>
0012 # include <boost/python/converter/rvalue_from_python_data.hpp>
0013 # include <boost/mpl/eval_if.hpp>
0014 # include <boost/mpl/if.hpp>
0015 # include <boost/mpl/identity.hpp>
0016 # include <boost/mpl/and.hpp>
0017 # include <boost/mpl/or.hpp>
0018 # include <boost/mpl/not.hpp>
0019 # include <boost/python/converter/registry.hpp>
0020 # include <boost/python/converter/registered.hpp>
0021 # include <boost/python/converter/registered_pointee.hpp>
0022 # include <boost/python/detail/void_ptr.hpp>
0023 # include <boost/python/back_reference.hpp>
0024 # include <boost/python/detail/referent_storage.hpp>
0025 # include <boost/python/converter/obj_mgr_arg_from_python.hpp>
0026 
0027 namespace boost { namespace python
0028 {
0029   template <class T> struct arg_from_python;
0030 }}
0031 
0032 // This header defines Python->C++ function argument converters,
0033 // parametrized on the argument type.
0034 
0035 namespace boost { namespace python { namespace converter {
0036 
0037 //
0038 // lvalue converters
0039 //
0040 //   These require that an lvalue of the type U is stored somewhere in
0041 //   the Python object being converted.
0042 
0043 // Used when T == U*const&
0044 template <class T>
0045 struct pointer_cref_arg_from_python
0046 {
0047     typedef T result_type;
0048     
0049     pointer_cref_arg_from_python(PyObject*);
0050     T operator()() const;
0051     bool convertible() const;
0052     
0053  private: // storage for a U*
0054     // needed because not all compilers will let us declare U* as the
0055     // return type of operator() -- we return U*const& instead
0056     typename python::detail::referent_storage<T>::type m_result;
0057 };
0058 
0059 // Base class for pointer and reference converters
0060 struct arg_lvalue_from_python_base
0061 {
0062  public: // member functions
0063     arg_lvalue_from_python_base(void* result);
0064     bool convertible() const;
0065     
0066  protected: // member functions
0067     void*const& result() const;
0068     
0069  private: // data members
0070     void* m_result;
0071 };
0072 
0073 // Used when T == U* 
0074 template <class T>
0075 struct pointer_arg_from_python : arg_lvalue_from_python_base
0076 {
0077     typedef T result_type;
0078     
0079     pointer_arg_from_python(PyObject*);
0080     T operator()() const;
0081 };
0082 
0083 // Used when T == U& and (T != V const& or T == W volatile&)
0084 template <class T>
0085 struct reference_arg_from_python : arg_lvalue_from_python_base
0086 {
0087     typedef T result_type;
0088     
0089     reference_arg_from_python(PyObject*);
0090     T operator()() const;
0091 };
0092 
0093 // ===================
0094 
0095 //
0096 // rvalue converters
0097 //
0098 //   These require only that an object of type T can be created from
0099 //   the given Python object, but not that the T object exist
0100 //   somewhere in storage.
0101 //
0102 
0103 // Used when T is a plain value (non-pointer, non-reference) type or
0104 // a (non-volatile) const reference to a plain value type.
0105 template <class T>
0106 struct arg_rvalue_from_python
0107 {
0108     typedef typename boost::python::detail::add_lvalue_reference<
0109         T
0110         // We can't add_const here, or it would be impossible to pass
0111         // auto_ptr<U> args from Python to C++
0112     >::type result_type;
0113     
0114     arg_rvalue_from_python(PyObject*);
0115     bool convertible() const;
0116 
0117 # if _MSC_FULL_VER > 13102196
0118     typename arg_rvalue_from_python<T>::
0119 # endif
0120     result_type operator()();
0121     
0122  private:
0123     rvalue_from_python_data<result_type> m_data;
0124     PyObject* m_source;
0125 };
0126 
0127 
0128 // ==================
0129 
0130 // Converts to a (PyObject*,T) bundle, for when you need a reference
0131 // back to the Python object
0132 template <class T>
0133 struct back_reference_arg_from_python
0134     : boost::python::arg_from_python<typename T::type>
0135 {
0136     typedef T result_type;
0137     
0138     back_reference_arg_from_python(PyObject*);
0139     T operator()();
0140  private:
0141     typedef boost::python::arg_from_python<typename T::type> base;
0142     PyObject* m_source;
0143 };
0144 
0145 
0146 // ==================
0147 
0148 template <class C, class T, class F>
0149 struct if_2
0150 {
0151     typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type;
0152 };
0153 
0154 // This metafunction selects the appropriate arg_from_python converter
0155 // type for an argument of type T.
0156 template <class T>
0157 struct select_arg_from_python
0158 {
0159     typedef typename if_2<
0160         is_object_manager<T>
0161       , object_manager_value_arg_from_python<T>
0162       , if_2<
0163             is_reference_to_object_manager<T>
0164           , object_manager_ref_arg_from_python<T>
0165           , if_2<
0166                 is_pointer<T>
0167               , pointer_arg_from_python<T>
0168               , if_2<
0169                     mpl::and_<
0170                         indirect_traits::is_reference_to_pointer<T>
0171                       , indirect_traits::is_reference_to_const<T>
0172                       , mpl::not_<indirect_traits::is_reference_to_volatile<T> >
0173                         >
0174                   , pointer_cref_arg_from_python<T>
0175                   , if_2<
0176                         mpl::or_<
0177                             indirect_traits::is_reference_to_non_const<T>
0178                           , indirect_traits::is_reference_to_volatile<T>
0179                         >
0180                       , reference_arg_from_python<T>
0181                       , mpl::if_<
0182                             boost::python::is_back_reference<T>
0183                           , back_reference_arg_from_python<T>
0184                           , arg_rvalue_from_python<T>
0185                         >
0186                     >
0187                 >
0188             >
0189         >
0190     >::type type;
0191 };
0192 
0193 // ==================
0194 
0195 //
0196 // implementations
0197 //
0198 
0199 // arg_lvalue_from_python_base
0200 //
0201 inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result)
0202     : m_result(result)
0203 {
0204 }
0205 
0206 inline bool arg_lvalue_from_python_base::convertible() const
0207 {
0208     return m_result != 0;
0209 }
0210 
0211 inline void*const& arg_lvalue_from_python_base::result() const
0212 {
0213     return m_result;
0214 }
0215 
0216 // pointer_cref_arg_from_python
0217 //
0218 namespace detail
0219 {
0220   // null_ptr_reference -- a function returning a reference to a null
0221   // pointer of type U. Needed so that extractors for T*const& can
0222   // convert Python's None.
0223   template <class T>
0224   struct null_ptr_owner
0225   {
0226       static T value;
0227   };
0228   template <class T> T null_ptr_owner<T>::value = 0;
0229   
0230   template <class U>
0231   inline U& null_ptr_reference(U&(*)())
0232   {
0233       return null_ptr_owner<U>::value;
0234   }
0235 }
0236 
0237 template <class T>
0238 inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p)
0239 {
0240     // T == U*const&: store a U* in the m_result storage. Nonzero
0241     // indicates success.  If find returns nonzero, it's a pointer to
0242     // a U object.
0243     python::detail::write_void_ptr_reference(
0244         m_result.bytes
0245         , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)
0246         , (T(*)())0);
0247 }
0248 
0249 template <class T>
0250 inline bool pointer_cref_arg_from_python<T>::convertible() const
0251 {
0252     return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
0253 }
0254 template <class T>
0255 inline T pointer_cref_arg_from_python<T>::operator()() const
0256 {
0257     return (*(void**)m_result.bytes == Py_None)  // None ==> 0
0258         ? detail::null_ptr_reference((T(*)())0)
0259         // Otherwise, return a U*const& to the m_result storage.
0260         : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
0261 }
0262 
0263 // pointer_arg_from_python
0264 //
0265 template <class T>
0266 inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
0267     : arg_lvalue_from_python_base(
0268         p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters))
0269 {
0270 }
0271 
0272 template <class T>
0273 inline T pointer_arg_from_python<T>::operator()() const
0274 {
0275     return (result() == Py_None) ? 0 : T(result());
0276 }
0277 
0278 // reference_arg_from_python
0279 //
0280 template <class T>
0281 inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
0282     : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters))
0283 {
0284 }
0285 
0286 template <class T>
0287 inline T reference_arg_from_python<T>::operator()() const
0288 {
0289     return python::detail::void_ptr_to_reference(result(), (T(*)())0);
0290 }
0291 
0292 
0293 // arg_rvalue_from_python
0294 //
0295 template <class T>
0296 inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
0297     : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
0298     , m_source(obj)
0299 {
0300 }
0301 
0302 template <class T>
0303 inline bool arg_rvalue_from_python<T>::convertible() const
0304 {
0305     return m_data.stage1.convertible != 0;
0306 }
0307 
0308 template <class T>
0309 inline typename arg_rvalue_from_python<T>::result_type
0310 arg_rvalue_from_python<T>::operator()()
0311 {
0312     if (m_data.stage1.construct != 0)
0313         m_data.stage1.construct(m_source, &m_data.stage1);
0314     
0315     return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
0316 }
0317 
0318 // back_reference_arg_from_python
0319 //
0320 template <class T>
0321 back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
0322   : base(x), m_source(x)
0323 {
0324 }
0325 
0326 template <class T>
0327 inline T
0328 back_reference_arg_from_python<T>::operator()()
0329 {
0330     return T(m_source, base::operator()());
0331 }
0332 
0333 }}} // namespace boost::python::converter
0334 
0335 #endif // ARG_FROM_PYTHON_DWA2002127_HPP