1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_PY_RESULT_CONVERSIONS_H
25 #define PXR_BASE_TF_PY_RESULT_CONVERSIONS_H
26 
27 #include "pxr/pxr.h"
28 
29 #include "pxr/base/tf/pyUtils.h"
30 
31 #include <boost/python/tuple.hpp>
32 #include <boost/python/list.hpp>
33 #include <boost/python/dict.hpp>
34 
35 #include <boost/type_traits/add_reference.hpp>
36 #include <boost/type_traits/remove_reference.hpp>
37 
38 #include <type_traits>
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 template <typename T> struct Tf_PySequenceToListConverter;
43 template <typename T> struct Tf_PySequenceToSetConverter;
44 template <typename T> struct Tf_PyMapToDictionaryConverter;
45 template <typename T> struct Tf_PySequenceToTupleConverter;
46 template <typename First, typename Second> struct Tf_PyPairToTupleConverter;
47 
48 /// \class TfPySequenceToList
49 ///
50 /// A \c boost::python result converter generator which converts standard
51 /// library sequences to lists.
52 ///
53 /// The way to use this is as a return value policy for a function which
54 /// returns a sequence or a const reference to a sequence.  For example this
55 /// function:
56 /// \code
57 /// vector<double> getDoubles() {
58 ///     vector<double> ret;
59 ///     ret.push_back(1.0);
60 ///     ret.push_back(2.0);
61 ///     ret.push_back(3.0);
62 ///     return ret;
63 /// }
64 /// \endcode
65 ///
66 /// May be wrapped as:
67 /// \code
68 /// def("getDoubles", &getDoubles, return_value_policy<TfPySequenceToList>())
69 /// \endcode
70 struct TfPySequenceToList {
71     template <typename T>
72     struct apply {
73         typedef Tf_PySequenceToListConverter<T> type;
74     };
75 };
76 
77 /// \class TfPySequenceToSet
78 ///
79 /// A \c boost::python result converter generator which converts standard
80 /// library sequences to sets.
81 ///
82 /// The way to use this is as a return value policy for a function which
83 /// returns a sequence or a const reference to a sequence.  For example this
84 /// function:
85 /// \code
86 /// unordered_set<double> getDoubles() {
87 ///     unordered_set<double> ret;
88 ///     ret.insert(1.0);
89 ///     ret.insert(2.0);
90 ///     ret.insert(3.0);
91 ///     return ret;
92 /// }
93 /// \endcode
94 ///
95 /// May be wrapped as:
96 /// \code
97 /// def("getDoubles", &getDoubles, return_value_policy<TfPySequenceToSet>())
98 /// \endcode
99 struct TfPySequenceToSet {
100     template <typename T>
101     struct apply {
102         typedef Tf_PySequenceToSetConverter<T> type;
103     };
104 };
105 
106 /// \class TfPyMapToDictionary
107 ///
108 /// A \c boost::python result converter generator which converts standard
109 /// library maps to dictionaries.
110 struct TfPyMapToDictionary {
111     template <typename T>
112     struct apply {
113         typedef Tf_PyMapToDictionaryConverter<T> type;
114     };
115 };
116 
117 /// \class TfPySequenceToTuple
118 ///
119 /// A \c boost::python result converter generator which converts standard
120 /// library sequences to tuples.
121 /// \see TfPySequenceToList.
122 struct TfPySequenceToTuple {
123     template <typename T>
124     struct apply {
125         typedef Tf_PySequenceToTupleConverter<T> type;
126     };
127 };
128 
129 /// A \c boost::python result converter generator which converts standard
130 /// library pairs to tuples.
131 struct TfPyPairToTuple {
132     template <typename T>
133     struct apply {
134         typedef Tf_PyPairToTupleConverter<typename T::first_type,
135                                           typename T::second_type> type;
136     };
137 };
138 
139 template <typename T>
140 struct Tf_PySequenceToListConverter {
141     typedef typename boost::remove_reference<T>::type SeqType;
convertibleTf_PySequenceToListConverter142     bool convertible() const {
143         return true;
144     }
operatorTf_PySequenceToListConverter145     PyObject *operator()(T seq) const {
146         return boost::python::incref(TfPyCopySequenceToList(seq).ptr());
147     }
get_pytypeTf_PySequenceToListConverter148     PyTypeObject *get_pytype() {
149         return &PyList_Type;
150     }
151 };
152 
153 template <typename T>
154 struct Tf_PySequenceToSetConverter {
155     typedef typename std::remove_reference<T>::type SeqType;
convertibleTf_PySequenceToSetConverter156     bool convertible() const {
157         return true;
158     }
operatorTf_PySequenceToSetConverter159     PyObject *operator()(T seq) const {
160         return boost::python::incref(TfPyCopySequenceToSet(seq).ptr());
161     }
get_pytypeTf_PySequenceToSetConverter162     PyTypeObject *get_pytype() {
163         return &PySet_Type;
164     }
165 };
166 
167 template <typename T>
168 struct Tf_PyMapToDictionaryConverter {
169     typedef typename boost::remove_reference<T>::type SeqType;
170     // TODO: convertible() should be made more robust by checking that the
171     // value_type of the container is pair<const key_type, data_type>
convertibleTf_PyMapToDictionaryConverter172     bool convertible() const {
173         return true;
174     }
operatorTf_PyMapToDictionaryConverter175     PyObject *operator()(T seq) const {
176         return boost::python::incref(TfPyCopyMapToDictionary(seq).ptr());
177     }
get_pytypeTf_PyMapToDictionaryConverter178     PyTypeObject *get_pytype() {
179         return &PyDict_Type;
180     }
181 };
182 
183 template <typename T>
184 struct Tf_PySequenceToTupleConverter {
185     typedef typename boost::remove_reference<T>::type SeqType;
convertibleTf_PySequenceToTupleConverter186     bool convertible() const {
187         return true;
188     }
operatorTf_PySequenceToTupleConverter189     PyObject *operator()(T seq) const {
190         return boost::python::incref(TfPyCopySequenceToTuple(seq).ptr());
191     }
get_pytypeTf_PySequenceToTupleConverter192     PyTypeObject *get_pytype() {
193         return &PyTuple_Type;
194     }
195 };
196 
197 template <typename First, typename Second>
198 struct Tf_PyPairToTupleConverter {
199     typedef std::pair<First, Second> PairType;
convertibleTf_PyPairToTupleConverter200     bool convertible() const {
201         return true;
202     }
operatorTf_PyPairToTupleConverter203     PyObject *operator()(PairType const& a) const {
204         boost::python::tuple result =
205             boost::python::make_tuple(a.first, a.second);
206         return boost::python::incref(result.ptr());
207     }
get_pytypeTf_PyPairToTupleConverter208     PyTypeObject *get_pytype() {
209         return &PyTuple_Type;
210     }
211 };
212 
213 PXR_NAMESPACE_CLOSE_SCOPE
214 
215 #endif // TF_RESULT_CONVERSIONS_H
216