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 terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_PY_OVERRIDE_H
8 #define PXR_BASE_TF_PY_OVERRIDE_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/base/tf/pyLock.h"
14 
15 #include "pxr/external/boost/python/override.hpp"
16 #include "pxr/external/boost/python/type.hpp"
17 
19 
20 /// \class TfPyMethodResult
21 ///
22 /// A reimplementation of pxr_boost::python::detail::method_result.
23 ///
24 /// This class is reimplemented from the boost class simply because the
25 /// provided class only allows construction from it's friended class
26 /// pxr_boost::python::override, which we also reimplement below.
27 ///
28 /// \see TfPyOverride
30 {
31 private:
32  /// Clients must hold GIL to construct.
33  friend class TfPyOverride;
34  explicit TfPyMethodResult(PyObject* x)
35  : m_obj(x)
36  {}
37 
38 public:
39  /// Implement copy to do python refcounting while holding the GIL.
40  TfPyMethodResult(TfPyMethodResult const &other);
41 
42  /// Implement dtor to do python refcounting while holding the GIL.
44 
45  /// Implement assign to do python refcounting while holding the GIL.
47 
48  template <class T>
49  operator T()
50  {
51  TfPyLock lock;
52  pxr_boost::python::converter::return_from_python<T> converter;
53  return converter(m_obj.release());
54  }
55 
56  template <class T>
57  operator T&() const
58  {
59  TfPyLock lock;
60  pxr_boost::python::converter::return_from_python<T&> converter;
61  return converter(
62  const_cast<pxr_boost::python::handle<>&>(m_obj).release());
63  }
64 
65  template <class T>
66  T as(pxr_boost::python::type<T>* = 0)
67  {
68  TfPyLock lock;
69  pxr_boost::python::converter::return_from_python<T> converter;
70  return converter(m_obj.release());
71  }
72 
73  template <class T>
74  T unchecked(pxr_boost::python::type<T>* = 0)
75  {
76  TfPyLock lock;
77  return pxr_boost::python::extract<T>(m_obj)();
78  }
79 
80 private:
81  mutable pxr_boost::python::handle<> m_obj;
82 };
83 
84 /// \class TfPyOverride
85 ///
86 /// A reimplementation of pxr_boost::python::override.
87 ///
88 /// This class is reimplemented from the boost class simply because the
89 /// provided class only allows construction from, ultimately,
90 /// pxr_boost::python::wrapper::get_override(). Unfortunately, that method
91 /// returns the wrong result when the overridden function we are asking about
92 /// lives not on the directly wrapped C++ class, but a wrapped ancestor.
93 /// So we provide our own version, TfPyOverride, with a public constructor.
94 ///
95 /// Note that clients must have the python GIL when constructing a
96 /// TfPyOverride object.
97 ///
99 {
100  // Helper to generate Py_BuildValue-style format strings at compile time.
101  template <typename Arg>
102  constexpr static char _PyObjArg()
103  {
104  return 'O';
105  }
106 
107 public:
108  /// Clients must hold the GIL to construct.
109  TfPyOverride(pxr_boost::python::handle<> callable)
110  : TfPyObjWrapper(pxr_boost::python::object(callable))
111  {}
112 
113  /// Call the override.
114  /// Clients need not hold the GIL to invoke the call operator.
115  template <typename... Args>
117  operator()(Args const&... args) const
118  {
119  TfPyLock lock;
120  // Use the Args parameter pack together with the _PyObjArg helper to
121  // unpack the right number of 'O' elements into the format string.
122  static const char pyCallFormat[] =
123  { '(', _PyObjArg<Args>()..., ')', '\0' };
124 
126  PyEval_CallFunction(
127  this->ptr(),
128  const_cast<char*>(pyCallFormat),
129  pxr_boost::python::converter::arg_to_python<Args>(args).get()...));
130  return x;
131  }
132 };
133 
135 
136 #endif // PXR_BASE_TF_PY_OVERRIDE_H
TfPyMethodResult & operator=(TfPyMethodResult const &other)
Implement assign to do python refcounting while holding the GIL.
T as(pxr_boost::python::type< T > *=0)
Definition: pyOverride.h:66
~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:117
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
T unchecked(pxr_boost::python::type< T > *=0)
Definition: pyOverride.h:74
auto ptr(T p) -> const void *
Definition: format.h:4331
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
**If you just want to fire and args
Definition: thread.h:618
TfPyOverride(pxr_boost::python::handle<> callable)
Clients must hold the GIL to construct.
Definition: pyOverride.h:109