| // Copyright David Abrahams 2002. |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| #ifndef LVALUE_FROM_PYTYPE_DWA2002130_HPP |
| # define LVALUE_FROM_PYTYPE_DWA2002130_HPP |
| |
| # include <boost/python/detail/prefix.hpp> |
| #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
| # include <boost/python/converter/pytype_function.hpp> |
| #endif |
| |
| # include <boost/python/type_id.hpp> |
| # include <boost/python/converter/registry.hpp> |
| # include <boost/python/detail/void_ptr.hpp> |
| |
| namespace boost { namespace python { |
| |
| namespace detail |
| { |
| // Given a pointer-to-function of 1 parameter returning a reference |
| // type, return the type_id of the function's return type. |
| template <class T, class U> |
| inline type_info extractor_type_id(T&(*)(U)) |
| { |
| return type_id<T>(); |
| } |
| |
| // A function generator whose static execute() function is an lvalue |
| // from_python converter using the given Extractor. U is expected to |
| // be the actual type of the PyObject instance from which the result |
| // is being extracted. |
| template <class Extractor, class U> |
| struct normalized_extractor |
| { |
| static inline void* execute(PyObject* op) |
| { |
| typedef typename boost::add_reference<U>::type param; |
| return &Extractor::execute( |
| boost::python::detail::void_ptr_to_reference( |
| op, (param(*)())0 ) |
| ); |
| } |
| }; |
| |
| // Given an Extractor type and a pointer to its execute function, |
| // return a new object whose static execute function does the same |
| // job but is a conforming lvalue from_python conversion function. |
| // |
| // usage: normalize<Extractor>(&Extractor::execute) |
| template <class Extractor, class T, class U> |
| inline normalized_extractor<Extractor,U> |
| normalize(T(*)(U), Extractor* = 0) |
| { |
| return normalized_extractor<Extractor, U>(); |
| } |
| } |
| |
| // An Extractor which extracts the given member from a Python object |
| // whose instances are stored as InstanceType. |
| template <class InstanceType, class MemberType, MemberType (InstanceType::*member)> |
| struct extract_member |
| { |
| static MemberType& execute(InstanceType& c) |
| { |
| (void)c.ob_type; // static assertion |
| return c.*member; |
| } |
| }; |
| |
| // An Extractor which simply extracts the entire python object |
| // instance of InstanceType. |
| template <class InstanceType> |
| struct extract_identity |
| { |
| static InstanceType& execute(InstanceType& c) |
| { |
| (void)c.ob_type; // static assertion |
| return c; |
| } |
| }; |
| |
| // Registers a from_python conversion which extracts lvalues using |
| // Extractor's static execute function from Python objects whose type |
| // object is python_type. |
| template <class Extractor, PyTypeObject const* python_type> |
| struct lvalue_from_pytype |
| { |
| lvalue_from_pytype() |
| { |
| converter::registry::insert |
| ( &extract |
| , detail::extractor_type_id(&Extractor::execute) |
| #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
| , &get_pytype |
| #endif |
| ); |
| } |
| private: |
| static void* extract(PyObject* op) |
| { |
| return PyObject_TypeCheck(op, const_cast<PyTypeObject*>(python_type)) |
| ? const_cast<void*>( |
| static_cast<void const volatile*>( |
| detail::normalize<Extractor>(&Extractor::execute).execute(op))) |
| : 0 |
| ; |
| } |
| #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
| static PyTypeObject const*get_pytype() { return python_type; } |
| #endif |
| }; |
| |
| }} // namespace boost::python |
| |
| #endif // LVALUE_FROM_PYTYPE_DWA2002130_HPP |