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