All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyOptional.h
Go to the documentation of this file.
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 TF_PYOPTIONAL_H
25 #define TF_PYOPTIONAL_H
26 
28 
29 #include "pxr/pxr.h"
30 
31 #include "pxr/base/tf/pyUtils.h"
32 #include <boost/noncopyable.hpp>
33 #include <boost/optional.hpp>
34 #include <boost/python/converter/from_python.hpp>
35 #include <boost/python/extract.hpp>
36 #include <boost/python/to_python_converter.hpp>
37 #include <boost/python/to_python_value.hpp>
38 
39 PXR_NAMESPACE_OPEN_SCOPE
40 
41 // Adapted from original at:
42 // http://mail.python.org/pipermail/cplusplus-sig/2007-May/012003.html
43 
44 namespace TfPyOptional {
45 
46 template <typename T, typename TfromPy>
47 struct object_from_python
48 {
49  object_from_python() {
50  boost::python::converter::registry::push_back
51  (&TfromPy::convertible, &TfromPy::construct,
52  boost::python::type_id<T>());
53  }
54 };
55 
56 template <typename T, typename TtoPy, typename TfromPy>
57 struct register_python_conversion
58 {
59  register_python_conversion() {
60  boost::python::to_python_converter<T, TtoPy>();
61  object_from_python<T, TfromPy>();
62  }
63 };
64 
65 template <typename T>
66 struct python_optional : public boost::noncopyable
67 {
68  struct optional_to_python
69  {
70  static PyObject * convert(const boost::optional<T>& value)
71  {
72  if (value) {
73  boost::python::object obj = TfPyObject(*value);
74  Py_INCREF(obj.ptr());
75  return obj.ptr();
76  }
77  return boost::python::detail::none();
78  }
79  };
80 
81  struct optional_from_python
82  {
83  static void * convertible(PyObject * source)
84  {
85  using namespace boost::python::converter;
86 
87  if ((source == Py_None) || boost::python::extract<T>(source).check())
88  return source;
89 
90  return NULL;
91  }
92 
93  static void construct(PyObject * source,
94  boost::python::converter::rvalue_from_python_stage1_data * data)
95  {
96  using namespace boost::python::converter;
97 
98  void * const storage =
99  ((rvalue_from_python_storage<T> *)data)->storage.bytes;
100 
101  if (data->convertible == Py_None) {
102  new (storage) boost::optional<T>(); // An uninitialized optional
103  } else {
104  new (storage) boost::optional<T>(boost::python::extract<T>(source));
105  }
106 
107  data->convertible = storage;
108  }
109  };
110 
111  explicit python_optional() {
112  register_python_conversion<boost::optional<T>,
113  optional_to_python, optional_from_python>();
114  }
115 };
116 
117 } // namespace TfPyOptional
118 
119 PXR_NAMESPACE_CLOSE_SCOPE
120 
121 #endif // TF_PYOPTIONAL_H
boost::python::object TfPyObject(T const &t, bool complainOnFailure=true)
Return a python object for the given C++ object, loading the appropriate wrapper code if necessary...
Definition: pyUtils.h:100