[857] | 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 LVALUE_FROM_PYTYPE_DWA2002130_HPP
|
---|
| 6 | # define LVALUE_FROM_PYTYPE_DWA2002130_HPP
|
---|
| 7 |
|
---|
| 8 | # include <boost/python/detail/prefix.hpp>
|
---|
| 9 |
|
---|
| 10 | # include <boost/python/type_id.hpp>
|
---|
| 11 | # include <boost/python/converter/registry.hpp>
|
---|
| 12 | # include <boost/python/detail/void_ptr.hpp>
|
---|
| 13 |
|
---|
| 14 | namespace boost { namespace python {
|
---|
| 15 |
|
---|
| 16 | namespace detail
|
---|
| 17 | {
|
---|
| 18 | // Given a pointer-to-function of 1 parameter returning a reference
|
---|
| 19 | // type, return the type_id of the function's return type.
|
---|
| 20 | template <class T, class U>
|
---|
| 21 | inline type_info extractor_type_id(T&(*)(U))
|
---|
| 22 | {
|
---|
| 23 | return type_id<T>();
|
---|
| 24 | }
|
---|
| 25 |
|
---|
| 26 | // A function generator whose static execute() function is an lvalue
|
---|
| 27 | // from_python converter using the given Extractor. U is expected to
|
---|
| 28 | // be the actual type of the PyObject instance from which the result
|
---|
| 29 | // is being extracted.
|
---|
| 30 | template <class Extractor, class U>
|
---|
| 31 | struct normalized_extractor
|
---|
| 32 | {
|
---|
| 33 | static inline void* execute(PyObject* op)
|
---|
| 34 | {
|
---|
| 35 | typedef typename boost::add_reference<U>::type param;
|
---|
| 36 | return &Extractor::execute(
|
---|
| 37 | boost::python::detail::void_ptr_to_reference(
|
---|
| 38 | op, (param(*)())0 )
|
---|
| 39 | );
|
---|
| 40 | }
|
---|
| 41 | };
|
---|
| 42 |
|
---|
| 43 | // Given an Extractor type and a pointer to its execute function,
|
---|
| 44 | // return a new object whose static execute function does the same
|
---|
| 45 | // job but is a conforming lvalue from_python conversion function.
|
---|
| 46 | //
|
---|
| 47 | // usage: normalize<Extractor>(&Extractor::execute)
|
---|
| 48 | template <class Extractor, class T, class U>
|
---|
| 49 | inline normalized_extractor<Extractor,U>
|
---|
| 50 | normalize(T(*)(U), Extractor* = 0)
|
---|
| 51 | {
|
---|
| 52 | return normalized_extractor<Extractor, U>();
|
---|
| 53 | }
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | // An Extractor which extracts the given member from a Python object
|
---|
| 57 | // whose instances are stored as InstanceType.
|
---|
| 58 | template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
|
---|
| 59 | struct extract_member
|
---|
| 60 | {
|
---|
| 61 | static MemberType& execute(InstanceType& c)
|
---|
| 62 | {
|
---|
| 63 | (void)c.ob_type; // static assertion
|
---|
| 64 | return c.*member;
|
---|
| 65 | }
|
---|
| 66 | };
|
---|
| 67 |
|
---|
| 68 | // An Extractor which simply extracts the entire python object
|
---|
| 69 | // instance of InstanceType.
|
---|
| 70 | template <class InstanceType>
|
---|
| 71 | struct extract_identity
|
---|
| 72 | {
|
---|
| 73 | static InstanceType& execute(InstanceType& c)
|
---|
| 74 | {
|
---|
| 75 | (void)c.ob_type; // static assertion
|
---|
| 76 | return c;
|
---|
| 77 | }
|
---|
| 78 | };
|
---|
| 79 |
|
---|
| 80 | // Registers a from_python conversion which extracts lvalues using
|
---|
| 81 | // Extractor's static execute function from Python objects whose type
|
---|
| 82 | // object is python_type.
|
---|
| 83 | template <class Extractor, PyTypeObject const* python_type>
|
---|
| 84 | struct lvalue_from_pytype
|
---|
| 85 | {
|
---|
| 86 | lvalue_from_pytype()
|
---|
| 87 | {
|
---|
| 88 | converter::registry::insert(
|
---|
| 89 | &extract, detail::extractor_type_id(&Extractor::execute));
|
---|
| 90 | }
|
---|
| 91 | private:
|
---|
| 92 | static void* extract(PyObject* op)
|
---|
| 93 | {
|
---|
| 94 | return PyObject_TypeCheck(op, const_cast<PyTypeObject*>(python_type))
|
---|
| 95 | ? const_cast<void*>(
|
---|
| 96 | static_cast<void const volatile*>(
|
---|
| 97 | detail::normalize<Extractor>(&Extractor::execute).execute(op)))
|
---|
| 98 | : 0
|
---|
| 99 | ;
|
---|
| 100 | }
|
---|
| 101 | };
|
---|
| 102 |
|
---|
| 103 | }} // namespace boost::python
|
---|
| 104 |
|
---|
| 105 | #endif // LVALUE_FROM_PYTYPE_DWA2002130_HPP
|
---|