Chris@16: // Copyright David Abrahams 2002. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef ARG_FROM_PYTHON_DWA2002127_HPP Chris@16: # define ARG_FROM_PYTHON_DWA2002127_HPP Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: namespace boost { namespace python Chris@16: { Chris@16: template struct arg_from_python; Chris@16: }} Chris@16: Chris@16: // This header defines Python->C++ function argument converters, Chris@16: // parametrized on the argument type. Chris@16: Chris@16: namespace boost { namespace python { namespace converter { Chris@16: Chris@16: // Chris@16: // lvalue converters Chris@16: // Chris@16: // These require that an lvalue of the type U is stored somewhere in Chris@16: // the Python object being converted. Chris@16: Chris@16: // Used when T == U*const& Chris@16: template Chris@16: struct pointer_cref_arg_from_python Chris@16: { Chris@16: typedef T result_type; Chris@16: Chris@16: pointer_cref_arg_from_python(PyObject*); Chris@16: T operator()() const; Chris@16: bool convertible() const; Chris@16: Chris@16: private: // storage for a U* Chris@16: // needed because not all compilers will let us declare U* as the Chris@16: // return type of operator() -- we return U*const& instead Chris@16: typename python::detail::referent_storage::type m_result; Chris@16: }; Chris@16: Chris@16: // Base class for pointer and reference converters Chris@16: struct arg_lvalue_from_python_base Chris@16: { Chris@16: public: // member functions Chris@16: arg_lvalue_from_python_base(void* result); Chris@16: bool convertible() const; Chris@16: Chris@16: protected: // member functions Chris@16: void*const& result() const; Chris@16: Chris@16: private: // data members Chris@16: void* m_result; Chris@16: }; Chris@16: Chris@16: // Used when T == U* Chris@16: template Chris@16: struct pointer_arg_from_python : arg_lvalue_from_python_base Chris@16: { Chris@16: typedef T result_type; Chris@16: Chris@16: pointer_arg_from_python(PyObject*); Chris@16: T operator()() const; Chris@16: }; Chris@16: Chris@16: // Used when T == U& and (T != V const& or T == W volatile&) Chris@16: template Chris@16: struct reference_arg_from_python : arg_lvalue_from_python_base Chris@16: { Chris@16: typedef T result_type; Chris@16: Chris@16: reference_arg_from_python(PyObject*); Chris@16: T operator()() const; Chris@16: }; Chris@16: Chris@16: // =================== Chris@16: Chris@16: // Chris@16: // rvalue converters Chris@16: // Chris@16: // These require only that an object of type T can be created from Chris@16: // the given Python object, but not that the T object exist Chris@16: // somewhere in storage. Chris@16: // Chris@16: Chris@16: // Used when T is a plain value (non-pointer, non-reference) type or Chris@16: // a (non-volatile) const reference to a plain value type. Chris@16: template Chris@16: struct arg_rvalue_from_python Chris@16: { Chris@16: typedef typename boost::add_reference< Chris@16: T Chris@16: // We can't add_const here, or it would be impossible to pass Chris@16: // auto_ptr args from Python to C++ Chris@16: >::type result_type; Chris@16: Chris@16: arg_rvalue_from_python(PyObject*); Chris@16: bool convertible() const; Chris@16: Chris@16: # if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196 Chris@16: typename arg_rvalue_from_python:: Chris@16: # endif Chris@16: result_type operator()(); Chris@16: Chris@16: private: Chris@16: rvalue_from_python_data m_data; Chris@16: PyObject* m_source; Chris@16: }; Chris@16: Chris@16: Chris@16: // ================== Chris@16: Chris@16: // Converts to a (PyObject*,T) bundle, for when you need a reference Chris@16: // back to the Python object Chris@16: template Chris@16: struct back_reference_arg_from_python Chris@16: : boost::python::arg_from_python Chris@16: { Chris@16: typedef T result_type; Chris@16: Chris@16: back_reference_arg_from_python(PyObject*); Chris@16: T operator()(); Chris@16: private: Chris@16: typedef boost::python::arg_from_python base; Chris@16: PyObject* m_source; Chris@16: }; Chris@16: Chris@16: Chris@16: // ================== Chris@16: Chris@16: template Chris@16: struct if_2 Chris@16: { Chris@16: typedef typename mpl::eval_if, F>::type type; Chris@16: }; Chris@16: Chris@16: // This metafunction selects the appropriate arg_from_python converter Chris@16: // type for an argument of type T. Chris@16: template Chris@16: struct select_arg_from_python Chris@16: { Chris@16: typedef typename if_2< Chris@16: is_object_manager Chris@16: , object_manager_value_arg_from_python Chris@16: , if_2< Chris@16: is_reference_to_object_manager Chris@16: , object_manager_ref_arg_from_python Chris@16: , if_2< Chris@16: is_pointer Chris@16: , pointer_arg_from_python Chris@16: , if_2< Chris@16: mpl::and_< Chris@16: indirect_traits::is_reference_to_pointer Chris@16: , indirect_traits::is_reference_to_const Chris@16: , mpl::not_ > Chris@16: > Chris@16: , pointer_cref_arg_from_python Chris@16: , if_2< Chris@16: mpl::or_< Chris@16: indirect_traits::is_reference_to_non_const Chris@16: , indirect_traits::is_reference_to_volatile Chris@16: > Chris@16: , reference_arg_from_python Chris@16: , mpl::if_< Chris@16: boost::python::is_back_reference Chris@16: , back_reference_arg_from_python Chris@16: , arg_rvalue_from_python Chris@16: > Chris@16: > Chris@16: > Chris@16: > Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // ================== Chris@16: Chris@16: // Chris@16: // implementations Chris@16: // Chris@16: Chris@16: // arg_lvalue_from_python_base Chris@16: // Chris@16: inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result) Chris@16: : m_result(result) Chris@16: { Chris@16: } Chris@16: Chris@16: inline bool arg_lvalue_from_python_base::convertible() const Chris@16: { Chris@16: return m_result != 0; Chris@16: } Chris@16: Chris@16: inline void*const& arg_lvalue_from_python_base::result() const Chris@16: { Chris@16: return m_result; Chris@16: } Chris@16: Chris@16: // pointer_cref_arg_from_python Chris@16: // Chris@16: namespace detail Chris@16: { Chris@16: // null_ptr_reference -- a function returning a reference to a null Chris@16: // pointer of type U. Needed so that extractors for T*const& can Chris@16: // convert Python's None. Chris@16: template Chris@16: struct null_ptr_owner Chris@16: { Chris@16: static T value; Chris@16: }; Chris@16: template T null_ptr_owner::value = 0; Chris@16: Chris@16: template Chris@16: inline U& null_ptr_reference(U&(*)()) Chris@16: { Chris@16: return null_ptr_owner::value; Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: inline pointer_cref_arg_from_python::pointer_cref_arg_from_python(PyObject* p) Chris@16: { Chris@16: // T == U*const&: store a U* in the m_result storage. Nonzero Chris@16: // indicates success. If find returns nonzero, it's a pointer to Chris@16: // a U object. Chris@16: python::detail::write_void_ptr_reference( Chris@16: m_result.bytes Chris@16: , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee::converters) Chris@16: , (T(*)())0); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool pointer_cref_arg_from_python::convertible() const Chris@16: { Chris@16: return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; Chris@16: } Chris@16: template Chris@16: inline T pointer_cref_arg_from_python::operator()() const Chris@16: { Chris@16: return (*(void**)m_result.bytes == Py_None) // None ==> 0 Chris@16: ? detail::null_ptr_reference((T(*)())0) Chris@16: // Otherwise, return a U*const& to the m_result storage. Chris@16: : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); Chris@16: } Chris@16: Chris@16: // pointer_arg_from_python Chris@16: // Chris@16: template Chris@16: inline pointer_arg_from_python::pointer_arg_from_python(PyObject* p) Chris@16: : arg_lvalue_from_python_base( Chris@16: p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee::converters)) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: inline T pointer_arg_from_python::operator()() const Chris@16: { Chris@16: return (result() == Py_None) ? 0 : T(result()); Chris@16: } Chris@16: Chris@16: // reference_arg_from_python Chris@16: // Chris@16: template Chris@16: inline reference_arg_from_python::reference_arg_from_python(PyObject* p) Chris@16: : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered::converters)) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: inline T reference_arg_from_python::operator()() const Chris@16: { Chris@16: return python::detail::void_ptr_to_reference(result(), (T(*)())0); Chris@16: } Chris@16: Chris@16: Chris@16: // arg_rvalue_from_python Chris@16: // Chris@16: template Chris@16: inline arg_rvalue_from_python::arg_rvalue_from_python(PyObject* obj) Chris@16: : m_data(converter::rvalue_from_python_stage1(obj, registered::converters)) Chris@16: , m_source(obj) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool arg_rvalue_from_python::convertible() const Chris@16: { Chris@16: return m_data.stage1.convertible != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename arg_rvalue_from_python::result_type Chris@16: arg_rvalue_from_python::operator()() Chris@16: { Chris@16: if (m_data.stage1.construct != 0) Chris@16: m_data.stage1.construct(m_source, &m_data.stage1); Chris@16: Chris@16: return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); Chris@16: } Chris@16: Chris@16: // back_reference_arg_from_python Chris@16: // Chris@16: template Chris@16: back_reference_arg_from_python::back_reference_arg_from_python(PyObject* x) Chris@16: : base(x), m_source(x) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: inline T Chris@16: back_reference_arg_from_python::operator()() Chris@16: { Chris@16: return T(m_source, base::operator()()); Chris@16: } Chris@16: Chris@16: }}} // namespace boost::python::converter Chris@16: Chris@16: #endif // ARG_FROM_PYTHON_DWA2002127_HPP