Loading...
Searching...
No Matches
pyOptional.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_PY_OPTIONAL_H
8#define PXR_BASE_TF_PY_OPTIONAL_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/base/tf/pyUtils.h"
15#include <boost/optional.hpp>
16#include <boost/python/converter/from_python.hpp>
17#include <boost/python/extract.hpp>
18#include <boost/python/to_python_converter.hpp>
19#include <boost/python/to_python_value.hpp>
20
21#include <optional>
22
23PXR_NAMESPACE_OPEN_SCOPE
24
25// Adapted from original at:
26// http://mail.python.org/pipermail/cplusplus-sig/2007-May/012003.html
27
28namespace TfPyOptional {
29
30template <typename T, typename TfromPy>
31struct object_from_python
32{
33 object_from_python() {
34 boost::python::converter::registry::push_back
35 (&TfromPy::convertible, &TfromPy::construct,
36 boost::python::type_id<T>());
37 }
38};
39
40template <typename T, typename TtoPy, typename TfromPy>
41struct register_python_conversion
42{
43 register_python_conversion() {
44 boost::python::to_python_converter<T, TtoPy>();
45 object_from_python<T, TfromPy>();
46 }
47};
48
49template <typename T>
50struct python_optional
51{
52 python_optional(const python_optional&) = delete;
53 python_optional& operator=(const python_optional&) = delete;
54 template <typename Optional>
55 struct optional_to_python
56 {
57 static PyObject * convert(const Optional& value)
58 {
59 if (value) {
60 boost::python::object obj = TfPyObject(*value);
61 Py_INCREF(obj.ptr());
62 return obj.ptr();
63 }
64 return boost::python::detail::none();
65 }
66 };
67
68 template <typename Optional>
69 struct optional_from_python
70 {
71 static void * convertible(PyObject * source)
72 {
73 using namespace boost::python::converter;
74
75 if ((source == Py_None) || boost::python::extract<T>(source).check())
76 return source;
77
78 return NULL;
79 }
80
81 static void construct(PyObject * source,
82 boost::python::converter::rvalue_from_python_stage1_data * data)
83 {
84 using namespace boost::python::converter;
85
86 void * const storage =
87 ((rvalue_from_python_storage<T> *)data)->storage.bytes;
88
89 if (data->convertible == Py_None) {
90 new (storage) Optional(); // An uninitialized optional
91 } else {
92 new (storage) Optional(boost::python::extract<T>(source));
93 }
94
95 data->convertible = storage;
96 }
97 };
98
99 explicit python_optional() {
100 register_python_conversion<
101 std::optional<T>,
102 optional_to_python<std::optional<T>>,
103 optional_from_python<std::optional<T>>>();
104 register_python_conversion<
105 boost::optional<T>,
106 optional_to_python<boost::optional<T>>,
107 optional_from_python<boost::optional<T>>>();
108 }
109};
110
111} // namespace TfPyOptional
112
113PXR_NAMESPACE_CLOSE_SCOPE
114
115#endif // PXR_BASE_TF_PY_OPTIONAL_H
Miscellaneous Utilities for dealing with script.
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:127