HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyOverride.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_TF_PY_OVERRIDE_H
25 #define PXR_BASE_TF_PY_OVERRIDE_H
26 
27 #include "pxr/pxr.h"
28 
29 #include "pxr/base/tf/pyLock.h"
31 
32 #include <hboost/python/override.hpp>
33 
35 
36 /// \class TfPyMethodResult
37 ///
38 /// A reimplementation of hboost::python::detail::method_result.
39 ///
40 /// This class is reimplemented from the hboost class simply because the
41 /// provided class only allows construction from it's friended class
42 /// hboost::python::override, which we also reimplement below.
43 ///
44 /// \see TfPyOverride
46 {
47 private:
48  /// Clients must hold GIL to construct.
49  friend class TfPyOverride;
50  explicit TfPyMethodResult(PyObject* x)
51  : m_obj(x)
52  {}
53 
54 public:
55  /// Implement copy to do python refcounting while holding the GIL.
56  TfPyMethodResult(TfPyMethodResult const &other);
57 
58  /// Implement dtor to do python refcounting while holding the GIL.
60 
61  /// Implement assign to do python refcounting while holding the GIL.
63 
64  template <class T>
65  operator T()
66  {
67  TfPyLock lock;
68  hboost::python::converter::return_from_python<T> converter;
69  return converter(m_obj.release());
70  }
71 
72  template <class T>
73  operator T&() const
74  {
75  TfPyLock lock;
76  hboost::python::converter::return_from_python<T&> converter;
77  return converter(
78  const_cast<hboost::python::handle<>&>(m_obj).release());
79  }
80 
81  template <class T>
82  T as(hboost::type<T>* = 0)
83  {
84  TfPyLock lock;
85  hboost::python::converter::return_from_python<T> converter;
86  return converter(m_obj.release());
87  }
88 
89  template <class T>
90  T unchecked(hboost::type<T>* = 0)
91  {
92  TfPyLock lock;
93  return hboost::python::extract<T>(m_obj)();
94  }
95 
96 private:
97  mutable hboost::python::handle<> m_obj;
98 };
99 
100 /// \class TfPyOverride
101 ///
102 /// A reimplementation of hboost::python::override.
103 ///
104 /// This class is reimplemented from the hboost class simply because the
105 /// provided class only allows construction from, ultimately,
106 /// hboost::python::wrapper::get_override(). Unfortunately, that method
107 /// returns the wrong result when the overridden function we are asking about
108 /// lives not on the directly wrapped C++ class, but a wrapped ancestor.
109 /// So we provide our own version, TfPyOverride, with a public constructor.
110 ///
111 /// Note that clients must have the python GIL when constructing a
112 /// TfPyOverride object.
113 ///
115 {
116  // Helper to generate Py_BuildValue-style format strings at compile time.
117  template <typename Arg>
118  constexpr static char _PyObjArg()
119  {
120  return 'O';
121  }
122 
123 public:
124  /// Clients must hold the GIL to construct.
125  TfPyOverride(hboost::python::handle<> callable)
126  : TfPyObjWrapper(hboost::python::object(callable))
127  {}
128 
129  /// Call the override.
130  /// Clients need not hold the GIL to invoke the call operator.
131  template <typename... Args>
133  operator()(Args const&... args) const
134  {
135  TfPyLock lock;
136  // Use the Args parameter pack together with the _PyObjArg helper to
137  // unpack the right number of 'O' elements into the format string.
138  static const char pyCallFormat[] =
139  { '(', _PyObjArg<Args>()..., ')', '\0' };
140 
142  PyEval_CallFunction(
143  this->ptr(),
144  const_cast<char*>(pyCallFormat),
145  hboost::python::converter::arg_to_python<Args>(args).get()...));
146  return x;
147  }
148 };
149 
151 
152 #endif // PXR_BASE_TF_PY_OVERRIDE_H
TfPyMethodResult & operator=(TfPyMethodResult const &other)
Implement assign to do python refcounting while holding the GIL.
T as(hboost::type< T > *=0)
Definition: pyOverride.h:82
T unchecked(hboost::type< T > *=0)
Definition: pyOverride.h:90
~TfPyMethodResult()
Implement dtor to do python refcounting while holding the GIL.
GLint GLenum GLint x
Definition: glcorearb.h:409
TfPyMethodResult operator()(Args const &...args) const
Definition: pyOverride.h:133
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
auto ptr(T p) -> const void *
Definition: format.h:2448
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
**If you just want to fire and args
Definition: thread.h:609
TfPyOverride(hboost::python::handle<> callable)
Clients must hold the GIL to construct.
Definition: pyOverride.h:125