Loading...
Searching...
No Matches
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 PXR_BASE_VT_VALUE_FROM_PYTHON_H
25#define PXR_BASE_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"
37
39
40#include <vector>
41
42PXR_NAMESPACE_OPEN_SCOPE
43
46class Vt_ValueFromPythonRegistry {
47public:
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
75private:
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
134VT_API_TEMPLATE_CLASS(TfSingleton<Vt_ValueFromPythonRegistry>);
135
136template <class T>
137VtValue 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
145template <class T>
146VtValue 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
154template <class T>
155void VtValueFromPython() {
156 Vt_ValueFromPythonRegistry::Register<T>(/* registerRvalue = */ true);
157}
158
159template <class T>
160void VtValueFromPythonLValue() {
161 Vt_ValueFromPythonRegistry::Register<T>(/* registerRvalue = */ false);
162}
163
164PXR_NAMESPACE_CLOSE_SCOPE
165
166#endif // PXR_BASE_VT_VALUE_FROM_PYTHON_H
Miscellaneous Utilities for dealing with script.
TF_API bool TfPyIsInitialized()
Returns true if python is initialized.
Manage a single instance of an object (see.
Definition: singleton.h:122
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:164
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:108
Intended to replace a direct include of Python.h, which causes several build problems with certain co...
Manage a single instance of an object.