All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
valueFromPython.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 VT_VALUE_FROM_PYTHON_H
25 #define VT_VALUE_FROM_PYTHON_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/base/vt/api.h"
31 #include "pxr/base/vt/value.h"
32 
33 #include "pxr/base/tf/hash.h"
34 #include "pxr/base/tf/hashmap.h"
35 #include "pxr/base/tf/pyUtils.h"
36 #include "pxr/base/tf/singleton.h"
37 
38 #include <Python.h>
39 
40 #include <vector>
41 
42 PXR_NAMESPACE_OPEN_SCOPE
43 
46 class Vt_ValueFromPythonRegistry {
47 public:
48 
49  static bool HasConversions() {
50  return !_GetInstance()._lvalueExtractors.empty() &&
51  !_GetInstance()._rvalueExtractors.empty();
52  }
53 
54  VT_API static VtValue Invoke(PyObject *obj);
55 
56  template <class T>
57  static void Register(bool registerRvalue) {
58  if (!TfPyIsInitialized()) {
59  TF_FATAL_ERROR("Tried to register a VtValue from python conversion "
60  "but python is not initialized!");
61  }
62  _GetInstance()._RegisterLValue(_Extractor::MakeLValue<T>());
63  if (registerRvalue)
64  _GetInstance()._RegisterRValue(_Extractor::MakeRValue<T>());
65  }
66 
67  Vt_ValueFromPythonRegistry(Vt_ValueFromPythonRegistry const&) = delete;
68  Vt_ValueFromPythonRegistry& operator=(
69  Vt_ValueFromPythonRegistry const&) = delete;
70 
71  Vt_ValueFromPythonRegistry(Vt_ValueFromPythonRegistry &&) = delete;
72  Vt_ValueFromPythonRegistry& operator=(
73  Vt_ValueFromPythonRegistry &&) = delete;
74 
75 private:
76  Vt_ValueFromPythonRegistry() {}
77  VT_API ~Vt_ValueFromPythonRegistry();
78 
79  friend class TfSingleton<Vt_ValueFromPythonRegistry>;
80 
81  class _Extractor {
82  private:
83  using _ExtractFunc = VtValue (*)(PyObject *);
84 
85  // _ExtractLValue will attempt to obtain an l-value T from the python
86  // object it's passed. This effectively disallows type conversions
87  // (other than things like derived-to-base type conversions).
88  template <class T>
89  static VtValue _ExtractLValue(PyObject *);
90 
91  // _ExtractRValue will attempt to obtain an r-value T from the python
92  // object it's passed. This allows boost.python to invoke type
93  // conversions to produce the T.
94  template <class T>
95  static VtValue _ExtractRValue(PyObject *);
96 
97  public:
98 
99  template <class T>
100  static _Extractor MakeLValue() {
101  return _Extractor(&_ExtractLValue<T>);
102  }
103 
104  template <class T>
105  static _Extractor MakeRValue() {
106  return _Extractor(&_ExtractRValue<T>);
107  }
108 
109  VtValue Invoke(PyObject *obj) const {
110  return _extract(obj);
111  }
112 
113  private:
114  explicit _Extractor(_ExtractFunc extract) : _extract(extract) {}
115 
116  _ExtractFunc _extract;
117  };
118 
119  VT_API static Vt_ValueFromPythonRegistry &_GetInstance() {
121  }
122 
123  VT_API void _RegisterLValue(_Extractor const &e);
124  VT_API void _RegisterRValue(_Extractor const &e);
125 
126  std::vector<_Extractor> _lvalueExtractors;
127  std::vector<_Extractor> _rvalueExtractors;
128 
129  typedef TfHashMap<PyObject *, _Extractor, TfHash> _LValueExtractorCache;
130  _LValueExtractorCache _lvalueExtractorCache;
131 
132 };
133 
134 VT_API_TEMPLATE_CLASS(TfSingleton<Vt_ValueFromPythonRegistry>);
135 
136 template <class T>
137 VtValue Vt_ValueFromPythonRegistry::
138 _Extractor::_ExtractLValue(PyObject *obj) {
139  boost::python::extract<T &> x(obj);
140  if (x.check())
141  return VtValue(x());
142  return VtValue();
143 }
144 
145 template <class T>
146 VtValue Vt_ValueFromPythonRegistry::
147 _Extractor::_ExtractRValue(PyObject *obj) {
148  boost::python::extract<T> x(obj);
149  if (x.check())
150  return VtValue(x());
151  return VtValue();
152 }
153 
154 template <class T>
155 void VtValueFromPython() {
156  Vt_ValueFromPythonRegistry::Register<T>(/* registerRvalue = */ true);
157 }
158 
159 template <class T>
160 void VtValueFromPythonLValue() {
161  Vt_ValueFromPythonRegistry::Register<T>(/* registerRvalue = */ false);
162 }
163 
164 PXR_NAMESPACE_CLOSE_SCOPE
165 
166 #endif // VT_VALUE_FROM_PYTHON_H
Manage a single instance of an object (see.
Definition: singleton.h:122
TF_API bool TfPyIsInitialized()
Returns true if python is initialized.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:111
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
Definition: singleton.h:137
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:182