HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyCall.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_CALL_H
8 #define PXR_BASE_TF_PY_CALL_H
9 
10 /// \file tf/pyCall.h
11 /// Utilities for calling python callables.
12 ///
13 /// These functions handle trapping python errors and converting them to \a
14 /// TfErrors.
15 
16 #include "pxr/pxr.h"
17 
18 #include "pxr/base/tf/pyError.h"
19 #include "pxr/base/tf/pyLock.h"
21 
22 #include "pxr/external/boost/python/call.hpp"
23 
25 
26 /// \class TfPyCall
27 ///
28 /// Provide a way to call a Python callable.
29 ///
30 /// Usage is as follows:
31 /// \code
32 /// return TfPyCall<RetType>(callable)(arg1, arg2, ... argN);
33 /// \endcode
34 /// Generally speaking, TfPyCall instances may be copied, assigned, destroyed,
35 /// and invoked without the client holding the GIL. However, if the \a Return
36 /// template parameter is a \a pxr_boost::python::object (or a derived class, such
37 /// as list or tuple) then the client must hold the GIL in order to invoke the
38 /// call operator.
39 template <typename Return>
40 struct TfPyCall {
41  /// Construct with callable \a c. Constructing with a \c
42  /// pxr_boost::python::object works, since those implicitly convert to \c
43  /// TfPyObjWrapper, however in that case the GIL must be held by the caller.
44  explicit TfPyCall(TfPyObjWrapper const &c) : _callable(c) {}
45 
46  template <typename... Args>
47  Return operator()(Args... args);
48 
49 private:
50  TfPyObjWrapper _callable;
51 };
52 
53 template <typename Return>
54 template <typename... Args>
55 inline Return
57 {
58  TfPyLock pyLock;
59  // Do *not* call through if there's an active python exception.
60  if (!PyErr_Occurred()) {
61  try {
62  return pxr_boost::python::call<Return>
63  (_callable.ptr(), args...);
64  } catch (pxr_boost::python::error_already_set const &) {
65  // Convert any exception to TF_ERRORs.
67  PyErr_Clear();
68  }
69  }
70  return Return();
71 }
72 
74 
75 #endif
Return operator()(Args...args)
Definition: pyCall.h:56
TfPyCall(TfPyObjWrapper const &c)
Definition: pyCall.h:44
TF_API void TfPyConvertPythonExceptionToTfErrors()
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
**If you just want to fire and args
Definition: thread.h:618