HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
makePyConstructor.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 
8 #ifndef PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H
9 #define PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H
10 
11 /// \file tf/makePyConstructor.h
12 /// An injected constructor mechanism that works with polymorphic wrapped
13 /// classes.
14 
15 #ifndef TF_MAX_ARITY
16 # define TF_MAX_ARITY 7
17 #endif // TF_MAX_ARITY
18 
19 
20 #include "pxr/pxr.h"
21 #include "pxr/base/tf/api.h"
23 #include "pxr/base/tf/refPtr.h"
24 #include "pxr/base/tf/weakPtr.h"
25 #include "pxr/base/tf/diagnostic.h"
26 #include "pxr/base/tf/pyError.h"
27 #include "pxr/base/tf/pyIdentity.h"
28 #include "pxr/base/tf/pyUtils.h"
30 
31 #include "pxr/base/arch/demangle.h"
32 
33 #include "pxr/external/boost/python/def_visitor.hpp"
34 #include "pxr/external/boost/python/dict.hpp"
35 #include "pxr/external/boost/python/errors.hpp"
36 #include "pxr/external/boost/python/list.hpp"
37 #include "pxr/external/boost/python/object/iterator.hpp"
38 #include "pxr/external/boost/python/raw_function.hpp"
39 #include "pxr/external/boost/python/tuple.hpp"
40 #include "pxr/external/boost/python/type_id.hpp"
41 
42 #include <array>
43 #include <string>
44 #include <type_traits>
45 #include <utility>
46 
48 
49 // Helper for wrapping objects that are held by weak pointers, but may also be
50 // constructed from script. This lets one construct an object from script and
51 // stores a ref pointer to the C++ object inside the python object. This way,
52 // objects created from script are owned by script, but objects obtained from
53 // the C++ API cannot be owned by script. When the owning python object is
54 // collected, its ref pointer will go away and the C++ object will be
55 // deallocated.
56 //
57 // Example usage:
58 //
59 // class_<MyClass, MyClassPtr>("MyClass", no_init)
60 // .def(TfPyRefAndWeakPtr())
61 // .def(TfMakePyConstructor(MyClass::New))
62 // .def(...)
63 // ...
64 //
65 // TfMakePyConstructorWithVarArgs may be used to wrap an object so that it
66 // may be constructed with a variable number of positional and keyword
67 // arguments. The last two arguments of the function being wrapped must
68 // be a pxr_boost::python::tuple and dict. These will contain the remaining
69 // positional and keyword args after required arguments are parsed.
70 //
71 // Example usage:
72 //
73 // static MyObjectRefPtr MyObjectFactory(
74 // int formalArg1, const std::string& formalArg2,
75 // const pxr_boost::python::tuple& args, const pxr_boost::python::dict& kwargs);
76 //
77 // class_<MyClass, MyClassPtr>("MyClass", no_init)
78 // .def(TfPyRefAndWeakPtr())
79 // .def(TfMakePyConstructorWithVarArgs(MyObjectFactory))
80 // .def(...)
81 //
82 // NOTE: The current implementation does not handle pxr_boost::python::arg for
83 // specifying keywords for required arguments.
84 
85 namespace Tf_MakePyConstructor {
86 
87 namespace bp = pxr_boost::python;
88 
89 template <typename CTOR>
90 struct InitVisitor : bp::def_visitor<InitVisitor<CTOR> > {
91  friend class bp::def_visitor_access;
92  const std::string _doc;
93  InitVisitor(const std::string &doc = std::string()) : _doc(doc) {}
94 
95  template <typename CLS>
96  void visit(CLS &c) const {
97  c.def("__init__", CTOR::template init_callable<CLS>(), _doc.c_str());
98  }
99 
100  template <class CLS, class Options>
101  void visit(CLS &c, char const* name, Options& options) const {
102  // Note: we ignore options.doc() in favor of _doc
103  c.def(name, CTOR::template init_callable<CLS>(options), _doc.c_str());
104  }
105 
106 };
107 
108 TF_API
109 bp::object _DummyInit(bp::tuple const & /* args */,
110  bp::dict const & /* kw */);
111 
112 template <typename CTOR>
113 struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
115  const std::string _doc;
116  NewVisitor(const std::string &doc = std::string()) : _doc(doc) {}
117 
118  template <typename CLS>
119  void visit(CLS &c) const {
120  // If there's already a __new__ method, look through the staticmethod to
121  // get the underlying function, replace __new__ with that, then add the
122  // overload, and recreate the staticmethod. This is required because
123  // boost python needs to have all overloads exported before you say
124  // .staticmethod.
125 
126  // Note that it looks like this should do nothing, but it actually does
127  // something! Here's what it does: looking up __new__ on c doesn't
128  // actually produce the staticmethod object -- it does a "descriptor
129  // __get__" which produces the underlying function. Replacing __new__
130  // with that underlying thing has the effect of unwrapping the
131  // staticmethod, which is exactly what we want.
132  if (PyObject_HasAttrString(c.ptr(), "__new__"))
133  c.attr("__new__") = c.attr("__new__");
134  c.def("__new__", CTOR::template __new__<CLS>, _doc.c_str());
135  c.staticmethod("__new__");
136 
137  //c.def("__init__", CTOR::template __init__<CLS>, _doc.c_str());
138  c.def("__init__", bp::raw_function(_DummyInit));
139  }
140 
141  template <class CLS, class Options>
142  void visit(CLS &c, char const* name, Options& options) const {
143  // If there's already a __new__ method, look through the staticmethod to
144  // get the underlying function, replace __new__ with that, then add the
145  // overload, and recreate the staticmethod. This is required because
146  // boost python needs to have all overloads exported before you say
147  // .staticmethod.
148 
149  // Note that it looks like this should do nothing, but it actually does
150  // something! Here's what it does: looking up __new__ on c doesn't
151  // actually produce the staticmethod object -- it does a "descriptor
152  // __get__" which produces the underlying function. Replacing __new__
153  // with that underlying thing has the effect of unwrapping the
154  // staticmethod, which is exactly what we want.
155  if (PyObject_HasAttrString(c.ptr(), "__new__"))
156  c.attr("__new__") = c.attr("__new__");
157  c.def("__new__", CTOR::template __new__<CLS>,
158  // Note: we ignore options.doc() in favor of _doc
159  _doc.c_str(),
160  options.keywords(),
161  options.policies()
162  );
163  c.staticmethod("__new__");
164 
165  //c.def("__init__", CTOR::template __init__<CLS>, _doc.c_str());
166  c.def("__init__", bp::raw_function(_DummyInit));
167  }
168 
169 };
170 
171 
173 
174 template <typename T>
176  static void PostInstall(object const &self, T const &t,
177  const void *) {}
178 };
179 
180 // Specialize install policy for refptrs.
181 template <typename T>
184  "Type T must support refcount unique changed notification.");
185  static void PostInstall(object const &self, TfRefPtr<T> const &ptr,
186  const void *uniqueId) {
187  // Stash a self-reference ref ptr into the python object that will
188  // keep the object alive. Need to get a ref ptr to the held type,
189  // since that's what's wrapped.
190  Tf_PyAddPythonOwnership(ptr, uniqueId, self.ptr());
191  }
192 };
193 
194 template <typename CLS, typename T>
195 void Install(object const &self, T const &t, TfErrorMark const &m) {
196  // Stick the weakptr into the python object self to complete
197  // construction.
198  typedef typename CLS::metadata::holder Holder;
199  typedef typename bp::objects::instance<Holder> instance_t;
200  typedef InstallPolicy<T> Policy;
201  typedef typename CLS::metadata::held_type HeldType;
202 
203  // CODE_COVERAGE_OFF
204  void *memory = Holder::
205  // CODE_COVERAGE_ON
206  allocate(self.ptr(), offsetof(instance_t, storage), sizeof(Holder));
207  try {
208  HeldType held(t);
209  Holder *holder = (new (memory) Holder(held));
210  // If there was a TfError, raise that back to python.
212  bp::throw_error_already_set();
213  // If no TfError, but object construction failed, raise a generic error
214  // back to python.
215  if (!held)
216  TfPyThrowRuntimeError("could not construct " +
217  ArchGetDemangled(typeid(HeldType)));
218  bp::detail::initialize_wrapper(self.ptr(), &(*(held.operator->())));
219  holder->install(self.ptr());
220 
221  // Set object identity
222  Tf_PySetPythonIdentity(held, self.ptr());
223 
224  Policy::PostInstall(self, t, held.GetUniqueIdentifier());
225 
226  } catch(...) {
227  Holder::deallocate(self.ptr(), memory); throw;
228  }
229 
230 }
231 
232 
233 template <typename WeakPtr, typename P>
235  typedef std::remove_reference_t<P> Ptr;
236  bool convertible() const {
237  // FIXME should actually check here... It's not really horrible because
238  // if the conversion will fail, we'll just get a runtime error down
239  // below when we try to create the resulting object. That's basically
240  // what we want anyway.
241  return true;
242  }
243  PyObject *operator()(Ptr const &p) const {
244  typedef InstallPolicy<Ptr> Policy;
245  WeakPtr ptr(static_cast<typename WeakPtr::DataType *>
246  (get_pointer(p)));
247 
248  // If resulting pointer is null, return None.
249  if (!ptr)
250  return bp::incref(Py_None);
251 
252  // The to-python converter will set identity here.
253  object result(ptr);
254 
255  Policy::PostInstall(result, p, ptr.GetUniqueIdentifier());
256  return bp::incref(result.ptr());
257  }
258  // Required for boost.python signature generator, in play when
259  // BOOST_PYTHON_NO_PY_SIGNATURES is undefined.
260  PyTypeObject const *get_pytype() const {
261  return pxr_boost::python::objects::registered_class_object(
262  pxr_boost::python::type_id<typename WeakPtr::DataType>()).get();
263  }
264 };
265 
266 template <typename WeakPtr = void>
268  template <typename FactoryResultPtr>
269  struct apply {
275  };
276 };
277 
278 // EXTRA_ARITY is added for InitCtorWithVarArgs backwards compatability.
279 // The previous BOOST_PP implementation didn't count the tuple and dict
280 // against the arity limit while the new version does. A future change
281 // should remove EXTRA_ARITY and increase TF_MAX_ARITY now that the
282 // implementations are templated and no longer generated by BOOST_PP
283 template <typename SIG, size_t EXTRA_ARITY = 0>
284 struct CtorBase {
285  typedef SIG Sig;
287  static_assert(Traits::Arity <= (TF_MAX_ARITY + EXTRA_ARITY));
288 
289  static Sig *_func;
290  static void SetFunc(Sig *func) {
291  if (!_func)
292  _func = func;
293  else {
294  // CODE_COVERAGE_OFF
295  TF_CODING_ERROR("Ctor with signature '%s' is already registered. "
296  "Duplicate will be ignored.",
297  ArchGetDemangled(typeid(Sig)).c_str());
298  // CODE_COVERAGE_ON
299  }
300  }
301 };
302 
303 template <typename SIG, size_t EXTRA_ARITY>
304 SIG *CtorBase<SIG, EXTRA_ARITY>::_func = nullptr;
305 
306 template <typename SIG> struct InitCtor;
307 template <typename SIG> struct InitCtorWithBackReference;
308 template <typename SIG> struct InitCtorWithVarArgs;
309 template <typename SIG> struct NewCtor;
310 template <typename SIG> struct NewCtorWithClassReference;
311 
312 }
313 
314 
315 template <typename T>
318 TfMakePyConstructor(T *func, const std::string &doc = std::string()) {
319  // Instantiate to set static constructor pointer, then return the visitor.
323 }
324 
325 template <typename T>
328 TfMakePyConstructorWithBackReference(T *func, const std::string &doc = std::string()) {
329  // Instantiate to set static constructor pointer, then return the visitor.
333 }
334 
335 template <typename T>
338 TfMakePyConstructorWithVarArgs(T *func, const std::string &doc = std::string()) {
339  // Instantiate to set static constructor pointer, then return the visitor.
343 }
344 
345 template <typename T>
348 TfMakePyNew(T *func, const std::string &doc = std::string()) {
349  // Instantiate to set static constructor pointer, then return the visitor.
353 }
354 
355 template <typename T>
358 TfMakePyNewWithClassReference(T *func, const std::string &doc = std::string()) {
359  // Instantiate to set static constructor pointer, then return the visitor.
363 }
364 
365 
366 template <typename T = void>
368 
369 template <typename T> struct Tf_PySequenceToListConverterRefPtrFactory;
370 
371 /// A \c pxr_boost::python result converter generator which converts standard
372 /// library sequences to lists of python owned objects.
374  template <typename T>
375  struct apply {
377  };
378 };
379 
380 // XXX: would be nicer to be able to compose converters with factory
381 template <typename T>
383  typedef std::remove_reference_t<T> SeqType;
384  bool convertible() const {
385  return true;
386  }
387  PyObject *operator()(T seq) const {
388  using namespace pxr_boost::python;
389 
392 
393  pxr_boost::python::list l;
394  for (typename SeqType::const_iterator i = seq.begin();
395  i != seq.end(); ++i) {
396  l.append(object(handle<>(RefPtrFactory()(*i))));
397  }
398  return pxr_boost::python::incref(l.ptr());
399  }
400  // Required for boost.python signature generator, in play when
401  // BOOST_PYTHON_NO_PY_SIGNATURES is undefined.
402  PyTypeObject const *get_pytype() const {
403  return &PyList_Type;
404  }
405 };
406 
407 namespace Tf_MakePyConstructor {
408 
409 template <typename R, typename... Args>
410 struct InitCtor<R(Args...)> : CtorBase<R(Args...)> {
411  typedef CtorBase<R(Args...)> Base;
412  typedef typename Base::Sig Sig;
413 
414  InitCtor(Sig* func) { Base::SetFunc(func); }
415 
416  template <typename CLS>
418  return bp::make_function(__init__<CLS>);
419  }
420 
421  template <typename CLS, typename Options>
422  static bp::object init_callable(Options& o) {
423  return bp::make_function(__init__<CLS>, o.policies(), o.keywords()) ;
424  }
425 
426  template <typename CLS>
427  static void __init__(object &self, Args... args) {
428  TfErrorMark m;
429  Install<CLS>(self, Base::_func(args...), m);
430  }
431 };
432 
433 template <typename R, typename... Args>
434 struct NewCtor<R(Args...)> : CtorBase<R(Args...)> {
435  typedef CtorBase<R(Args...)> Base;
436  typedef typename Base::Sig Sig;
437  NewCtor(Sig *func) { Base::SetFunc(func); }
438 
439  template <class CLS>
440  static bp::object __new__(object &cls, Args... args) {
441  typedef typename CLS::metadata::held_type HeldType;
442  TfErrorMark m;
443  R r((Base::_func(args...)));
444  HeldType h((r));
446  bp::throw_error_already_set();
447  bp::object ret = TfPyObject(h);
448  if (TfPyIsNone(ret))
449  TfPyThrowRuntimeError("could not construct " +
450  ArchGetDemangled(typeid(HeldType)));
451 
452  bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
453  // make the object have the right class.
454  bp::setattr(ret, "__class__", cls);
455 
456  InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
457  return ret;
458  }
459 };
460 
461 template <typename R, typename... Args>
462 struct InitCtorWithVarArgs<R(Args...)> :
463  // Pad the arity for backwards compatability
464  CtorBase<R(Args...), /*EXTRA_ARITY*/ 2> {
465  typedef CtorBase<R(Args...), /*EXTRA_ARITY*/ 2> Base;
466  typedef typename Base::Sig Sig;
467 
468  // Ideally, Arity would be pulled from Base::Traits, but
469  // compilers have inconsistently allowed this. Redefine
470  // Arity as a workaround for now.
471  using Arity = TfMetaLength<Args...>;
472 
473  InitCtorWithVarArgs(Sig *func) { Base::SetFunc(func); }
474 
475  static_assert((Arity::value >= 2) &&
476  (std::is_same_v<
477  const bp::tuple&,
478  typename Base::Traits::template NthArg<(Arity::value-2)>>) &&
479  (std::is_same_v<
480  const bp::dict&,
481  typename Base::Traits::template NthArg<(Arity::value-1)>>),
482  "InitCtorWithVarArgs requires a function of form "
483  "(..., const tuple&, const dict&)");
484 
485  template <typename CLS>
487  // Specify min_args as 1 to account for just the 'self' argument.
488  // min_args really should be N + 1. However, we want to do this check
489  // ourselves later so we can emit a better error message.
490  return bp::raw_function(__init__<CLS>, /* min_args = */ 1);
491  }
492 
493  template <typename CLS, typename Options>
494  static bp::object init_callable(Options& options) {
495  // XXX: Note ignoring options.keywords(), current implementation can't
496  // handle that correctly.
497  return bp::raw_function(
498  bp::make_function(__init__<CLS>, options.policies()),
499  /* min_args = */ 1);
500  }
501 
502  template <typename CLS, size_t... I>
503  static bp::object __init__impl(const bp::tuple& args,
504  const bp::dict& kwargs,
505  std::index_sequence<I...>) {
506  TfErrorMark m;
507 
508  // We know that there are at least two args because the specialization only
509  // matches against (..., *args, **kwargs)
510  const unsigned int expectedNamedArgs = Arity::value - 2;
511  // self is included in the tuple, so it should always be at least 1
512  const unsigned int positionalArgs = bp::len(args) - 1;
513  if (positionalArgs < expectedNamedArgs) {
514  std::array<std::string, Arity::value - 2>
515  positionalArgTypes = {{
516  (bp::type_id<typename Base::Traits::template NthArg<I>>().name())...
517  }};
518  std::string joinedTypes = TfStringJoin(
519  std::begin(positionalArgTypes),
520  std::end(positionalArgTypes), ", "
521  );
522  if (!joinedTypes.empty()) {
523  joinedTypes += ", ";
524  }
525  // User didn't provide enough positional arguments for the factory
526  // function. Complain.
529  "Arguments to __init__ did not match C++ signature:\n"
530  "\t__init__(%s...)", joinedTypes.c_str()
531  )
532  );
533  return bp::object();
534  }
535 
536  Install<CLS>(
537  // self object for new instance is the first arg to __init__
538  args[0],
539  Base::_func(
540  bp::extract<
542  typename Base::Traits::template NthArg<I>>>(args[I + 1])...,
543  bp::tuple(args.slice(expectedNamedArgs + 1, bp::len(args))), kwargs),
544  m);
545 
546  return bp::object();
547  }
548 
549  template <typename CLS>
550  static bp::object __init__(const bp::tuple& args,
551  const bp::dict& kwargs) {
552  return __init__impl<CLS>(
553  args, kwargs, std::make_index_sequence<Arity::value - 2>());
554 
555  }
556 };
557 
558 // This is a variant of Ctor which includes a back reference to self
559 // (the Python object being initialized) in the args passed to the
560 // constructor. This is used to expose the factory methods for classes
561 // which we expect to subclass in Python. When the constructor is called,
562 // it can examine self and initialize itself appropriately.
563 template <typename R, typename SelfRef, typename... Args>
564 struct InitCtorWithBackReference<R(SelfRef, Args...)> :
565  CtorBase<R(SelfRef, Args...)> {
566  typedef CtorBase<R(SelfRef, Args...)> Base;
567  typedef typename Base::Sig Sig;
568  InitCtorWithBackReference(Sig *func) { Base::SetFunc(func); }
569 
570  template <typename CLS>
572  return bp::make_function(__init__<CLS>);
573  }
574 
575  template <typename CLS, typename Options>
576  static bp::object init_callable(Options& o) {
577  return bp::make_function(__init__<CLS>, o.policies(), o.keywords());
578  }
579 
580  template <typename CLS>
581  static void __init__(SelfRef self, Args... args) {
582  TfErrorMark m;
583  Install<CLS>(self, Base::_func(self, args...), m);
584  }
585 };
586 
587 template <typename R, typename ClsRef, typename... Args>
588 struct NewCtorWithClassReference<R(ClsRef, Args...)> :
589  CtorBase<R(ClsRef, Args...)> {
590  typedef CtorBase<R(ClsRef, Args...)> Base;
591  typedef typename Base::Sig Sig;
592  NewCtorWithClassReference(Sig *func) { Base::SetFunc(func); }
593 
594  template <class CLS>
595  static bp::object __new__(ClsRef cls, Args... args) {
596  typedef typename CLS::metadata::held_type HeldType;
597  TfErrorMark m;
598  R r(Base::_func(cls, args...));
599  HeldType h(r);
601  bp::throw_error_already_set();
602  bp::object ret = TfPyObject(h);
603  if (TfPyIsNone(ret))
604  TfPyThrowRuntimeError("could not construct " +
605  ArchGetDemangled(typeid(HeldType)));
606 
607  bp::detail::initialize_wrapper(ret.ptr(), get_pointer(h));
608  // make the object have the right class.
609  bp::setattr(ret, "__class__", cls);
610 
611  InstallPolicy<R>::PostInstall(ret, r, h.GetUniqueIdentifier());
612  return ret;
613  }
614 };
615 }
616 
618 
619 #endif // PXR_BASE_TF_MAKE_PY_CONSTRUCTOR_H
GLsizei GLenum GLsizei GLsizei GLuint memory
Definition: RE_OGL.h:202
Tf_MakePyConstructor::NewVisitor< typename Tf_MakePyConstructor::NewCtor< T > > TfMakePyNew(T *func, const std::string &doc=std::string())
type
Definition: core.h:556
TF_API std::string TfStringPrintf(const char *fmt,...)
Tf_MakePyConstructor::InitVisitor< typename Tf_MakePyConstructor::InitCtor< T > > TfMakePyConstructor(T *func, const std::string &doc=std::string())
std::integral_constant< size_t, sizeof...(Xs)> TfMetaLength
Definition: meta.h:54
#define TF_API
Definition: api.h:23
_RefPtrFactoryConverter< WeakPtrType, FactoryResultPtr > type
pxr_boost::python::object TfPyObject(T const &t, bool complainOnFailure=true)
Definition: pyUtils.h:127
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:266
GLsizei const GLfloat * value
Definition: glcorearb.h:824
Tf_MakePyConstructor::InitVisitor< typename Tf_MakePyConstructor::InitCtorWithVarArgs< T > > TfMakePyConstructorWithVarArgs(T *func, const std::string &doc=std::string())
#define TF_CODING_ERROR
Tf_PySequenceToListConverterRefPtrFactory< T > type
PyObject * operator()(Ptr const &p) const
static bp::object __init__impl(const bp::tuple &args, const bp::dict &kwargs, std::index_sequence< I...>)
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
static void SetFunc(Sig *func)
**But if you need a result
Definition: thread.h:622
#define TF_MAX_ARITY
PyTypeObject const * get_pytype() const
Tf_MakePyConstructor::InitVisitor< typename Tf_MakePyConstructor::InitCtorWithBackReference< T > > TfMakePyConstructorWithBackReference(T *func, const std::string &doc=std::string())
PXR_NAMESPACE_OPEN_SCOPE TF_API bool TfPyConvertTfErrorsToPythonException(TfErrorMark const &m)
Tf_MakePyConstructor::NewVisitor< typename Tf_MakePyConstructor::NewCtorWithClassReference< T > > TfMakePyNewWithClassReference(T *func, const std::string &doc=std::string())
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:63
std::decay_t< decltype(make_index_sequence_impl< N >())> make_index_sequence
Definition: Types.h:234
OIIO_FORCEINLINE bool extract(const vbool4 &a)
Definition: simd.h:3542
std::weak_ptr< T > WeakPtr
Definition: Types.h:115
NewVisitor(const std::string &doc=std::string())
TF_API bool TfPyIsNone(pxr_boost::python::object const &obj)
Return true iff obj is None.
static bp::object __new__(object &cls, Args...args)
InitVisitor(const std::string &doc=std::string())
GLuint GLuint end
Definition: glcorearb.h:475
TF_API void TfPyThrowTypeError(const char *msg)
typename std::remove_reference< T >::type remove_reference_t
Definition: core.h:269
GLuint const GLchar * name
Definition: glcorearb.h:786
std::string TfStringJoin(ForwardIterator begin, ForwardIterator end, const char *separator=" ")
Definition: stringUtils.h:358
GLdouble t
Definition: glad.h:2397
void visit(CLS &c, char const *name, Options &options) const
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
GLenum func
Definition: glcorearb.h:783
std::enable_if_t< Tf_PyIsRefPtr< Ptr >::value > Tf_PySetPythonIdentity(Ptr const &, PyObject *)
Definition: pyIdentity.h:196
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
static void __init__(object &self, Args...args)
void Tf_PyAddPythonOwnership(Ptr const &t, const void *uniqueId, PyObject *obj)
Definition: pyIdentity.h:226
auto ptr(T p) -> const void *
Definition: format.h:4331
TF_API bp::object _DummyInit(bp::tuple const &, bp::dict const &)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void Install(object const &self, T const &t, TfErrorMark const &m)
**If you just want to fire and args
Definition: thread.h:618
OIIO_UTIL_API const char * c_str(string_view str)
std::conditional_t< std::is_same< WeakPtr, void >::value, TfWeakPtr< typename FactoryResultPtr::DataType >, WeakPtr > WeakPtrType
TfFunctionTraits< R(SelfRef, Args...)* > Traits
GLboolean r
Definition: glcorearb.h:1222
static void PostInstall(object const &self, TfRefPtr< T > const &ptr, const void *uniqueId)
typename Tf_GetFuncSig< Fn >::Type TfFunctionTraits
static void PostInstall(object const &self, T const &t, const void *)
TF_API void TfPyThrowRuntimeError(const char *msg)
static bp::object __init__(const bp::tuple &args, const bp::dict &kwargs)
void visit(CLS &c, char const *name, Options &options) const
static bp::object init_callable(Options &o)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566