]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 extractor_type_id(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 normalized_extractor | |
35 | { | |
36 | static inline void* execute(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 extract_member | |
63 | { | |
64 | static MemberType& execute(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 extract_identity | |
75 | { | |
76 | static InstanceType& execute(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* extract(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 |