HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PY_Callback.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * COMMENTS:
7  * Instances of this class hold a Python callback (any callable Python
8  * object). You can invoke this callback with the call() method, passing
9  * it optional arguments. When this object is destroyed, the reference
10  * count on the Python callback will be decremented.
11  */
12 
13 #ifndef __PY_Callback_h__
14 #define __PY_Callback_h__
15 
16 #include "PY_API.h"
17 #include "PY_CompiledCode.h"
18 #include "PY_InterpreterAutoLock.h"
19 #include "PY_EvaluationContext.h"
20 #include "PY_OpaqueObject.h"
21 #include "PY_Result.h"
22 #include "PY_Kwargs.h"
23 
24 #include <UT/UT_Function.h>
25 #include <UT/UT_NonCopyable.h>
26 #include <UT/UT_StringHolder.h>
27 #include <UT/UT_StringMap.h>
28 #include <UT/UT_UniquePtr.h>
29 
30 class PY_PyObject;
31 class BM_View;
32 class FUSE_Office;
33 class OP_Node;
34 
35 // A cache to avoid recompiling PY_CompiledCode.
37 {
38 public:
39  PY_CallbackCompiledCodeCache(exint cache_size=100);
41 
42  PY_CompiledCode *compile(const UT_StringHolder &code);
43 
46 
48 };
49 
50 // Interface class implemented in HOMUI/HOMF which allows allows code in low
51 // level libraries such as PY and BM to create HOM wrapper instances.
52 // This can be used to avoid generating code that has a pointer as an int64 in
53 // its python code string.
55 {
56 public:
57  PY_CallbackHOM() = default;
58  virtual ~PY_CallbackHOM(){}
59 
61 
62  virtual bool getDesktopOffice(const BM_View& v, int &desktop_id, int &office_id) = 0;
63  virtual FUSE_Office *getOffice(const BM_View& v) = 0;
64 
65  // Returns True if the viewer office is usable
66  virtual bool isValidViewerOffice(const BM_View& v) const = 0;
67 
68  virtual PY_PyObject *newNode(OP_Node &node) = 0;
69  virtual PY_PyObject *newSceneViewer(FUSE_Office &office, bool convert_context_viewer=false) = 0;
70  virtual PY_PyObject *newViewerStateContext(int64 val) = 0;
71  virtual PY_PyObject *newUIEvent(int64 val, int64 val2) = 0;
72  virtual PY_PyObject *newViewerEvent(int desktop, int office, int64 val, int64 val2) = 0;
73  virtual PY_PyObject *newCompositorViewerEvent(int desktop, int office, int64 val, int64 val2) = 0;
74  virtual PY_PyObject *newCompositorViewer(FUSE_Office &office) = 0;
75 };
76 
78 {
79 public:
81 
82  PY_Callback() noexcept : PY_OpaqueObject()
83  {};
84  PY_Callback(std::nullptr_t n) noexcept : PY_OpaqueObject(n)
85  {};
86 
87  // Construct instances of this class with an opaque PY_PyObject
88  // containing a callable Python object.
89  explicit
90  PY_Callback(void *python_callable_object, bool new_ref = false) noexcept
91  : PY_OpaqueObject(python_callable_object, new_ref)
92  , myExpressionCache(nullptr)
93  {}
94 
95  /// Copy construct/assign
96  /// @{
97  PY_Callback(const PY_Callback &callback) noexcept
98  : PY_OpaqueObject(callback)
99  , myExpressionCache(nullptr)
100  {}
101  PY_Callback &operator=(const PY_Callback &callback) noexcept
102  { return (PY_Callback &)PY_OpaqueObject::operator=(callback); }
103  /// @}
104 
105  /// Move construct/assign
106  /// @{
107  PY_Callback(PY_Callback &&callback) noexcept
108  : PY_OpaqueObject(std::forward<PY_Callback>(callback))
109  , myExpressionCache(nullptr)
110  {
111  }
112  PY_Callback &operator=(PY_Callback &&callback) noexcept
113  {
115  std::forward<PY_Callback>(callback));
116  }
117  /// @}
118 
119  // Given two strings containing Python expressions (one that evaluates to
120  // a tuple of arguments and another that evaluates to a dictionary of
121  // keyword arguments), call the callback. Either or both of the argument
122  // tuple and keyword argument dictionary may be null. The result is
123  // returned in the PY_Result object.
124  void call(PY_Result &result, const char *args_expression=NULL,
125  const char *kwargs_expression=NULL) const;
126 
127  // This convenience version of call() returns the PY_Result by value,
128  // instead of passing it in by reference. This versions can be used by
129  // code that isn't performance-critical.
130  PY_Result call(const char *args_expression=NULL,
131  const char *kwargs_expression=NULL) const
132  {
134  call(result, args_expression, kwargs_expression);
135  return result;
136  }
137 
138  // For callbacks returning values
139  PY_Result call(
140  const char *args_expression,
141  const char *kwargs_expression,
142  PY_Result::Type desired_result_type ) const;
143 
144  // Similar to the above methods but take a lambda function to add elements to
145  // the evaluated expressions before firing the callback. Also takes a module name
146  // to evaluate the expressions, the module is optional and can be set to nullptr if
147  // not required.
148  //
150  const char* args_expression,
151  const char* kwargs_expression,
152  const char* module_name,
153  PY_Result::Type desired_result_type,
154  PY_OpaqueObject& out_args,
155  PY_OpaqueObject& out_kwargs,
156  ArgHandler arg_handler ) const
157  {
158  PY_InterpreterAutoLock auto_lock;
159 
160  PY_Result result = evaluateArgs(
161  args_expression, kwargs_expression, module_name, out_args, out_kwargs, arg_handler);
162  if (result.myResultType == PY_Result::ERR)
163  {
164  return result;
165  }
166 
167  return call(out_args.pyObject(), out_kwargs.pyObject(),
168  desired_result_type);
169  }
170 
171  // Evaluates argument expressions and use a lambda function for
172  // adding extra elements to the arg and kwarg objects.
174  const char* args_expression,
175  const char* kwargs_expression,
176  const char* module_name,
177  PY_OpaqueObject& out_args,
178  PY_OpaqueObject& out_kwargs,
179  ArgHandler arg_handler ) const
180  {
181  PY_InterpreterAutoLock auto_lock;
182 
183  PY_Result result = evaluate(
184  args_expression, kwargs_expression, module_name, out_args, out_kwargs);
185  if (result.myResultType == PY_Result::ERR)
186  {
187  return result;
188  }
189 
190  arg_handler(out_args.pyObject(), out_kwargs.pyObject());
191 
192  return result;
193  }
194 
196  { myExpressionCache = c; }
197 
198  static void setHOM(PY_CallbackHOM *hom)
199  { theHOM = hom; }
200 
202  { return theHOM; }
203 
204 private:
205  // Performs a call with pre-evaluated args and kwargs
206  PY_Result call(
207  PY_PyObject * args,
208  PY_PyObject * kwargs,
209  PY_Result::Type desired_result_type=PY_Result::NONE ) const;
210 
211  // Evaluates positional and keyworded arguments. The returned arguments can
212  // be expanded with other values before performing a call.
213  PY_Result evaluate(
214  const char *args_expression,
215  const char *kwargs_expression,
216  const char *module_name,
217  PY_OpaqueObject& out_args,
218  PY_OpaqueObject& out_kwargs ) const;
219 
220  PY_OpaqueObject evaluateExpression(const char *expression, PY_Result &result) const;
221  // This version use an input module to evaluate the expression
222  PY_OpaqueObject evaluateExpression(
223  const char *expression, const char* module_name, PY_Result &result) const;
224 
225  PY_CallbackCompiledCodeCache *myExpressionCache;
226 
227  static PY_CallbackHOM *theHOM;
228 };
229 
230 #endif
virtual ~PY_CallbackHOM()
Definition: PY_Callback.h:58
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:632
const GLdouble * v
Definition: glcorearb.h:837
int64 exint
Definition: SYS_Types.h:125
PY_Callback & operator=(PY_Callback &&callback) noexcept
Definition: PY_Callback.h:112
**But if you need a result
Definition: thread.h:622
static void setHOM(PY_CallbackHOM *hom)
Definition: PY_Callback.h:198
GLdouble n
Definition: glcorearb.h:2008
static PY_CallbackHOM * getHOM()
Definition: PY_Callback.h:201
UT_StringMap< PY_CompiledCode * > myExpressionCache
Definition: PY_Callback.h:45
PY_Result evaluateArgs(const char *args_expression, const char *kwargs_expression, const char *module_name, PY_OpaqueObject &out_args, PY_OpaqueObject &out_kwargs, ArgHandler arg_handler) const
Definition: PY_Callback.h:173
PY_Callback(void *python_callable_object, bool new_ref=false) noexcept
Definition: PY_Callback.h:90
PY_Callback(std::nullptr_t n) noexcept
Definition: PY_Callback.h:84
PY_EvaluationContext myContext
Definition: PY_Callback.h:44
PY_PyObject
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
#define PY_API
Definition: PY_API.h:10
long long int64
Definition: SYS_Types.h:116
std::function< T > UT_Function
Definition: UT_Function.h:37
PY_Callback & operator=(const PY_Callback &callback) noexcept
Definition: PY_Callback.h:101
PY_OpaqueObject & operator=(const PY_OpaqueObject &opaque_object) noexcept
PY_Callback(const PY_Callback &callback) noexcept
Definition: PY_Callback.h:97
PY_Result call(const char *args_expression, const char *kwargs_expression, const char *module_name, PY_Result::Type desired_result_type, PY_OpaqueObject &out_args, PY_OpaqueObject &out_kwargs, ArgHandler arg_handler) const
Definition: PY_Callback.h:149
PY_Callback() noexcept
Definition: PY_Callback.h:82
void setExpressionCache(PY_CallbackCompiledCodeCache *c)
Definition: PY_Callback.h:195
GLuint GLfloat * val
Definition: glcorearb.h:1608
**If you just want to fire and args
Definition: thread.h:618
PY_Callback(PY_Callback &&callback) noexcept
Definition: PY_Callback.h:107
UT_Function< void(PY_PyObject *args, PY_PyObject *kwargs)> ArgHandler
Definition: PY_Callback.h:80
Type myResultType
Definition: PY_Result.h:45
PY_Result call(const char *args_expression=NULL, const char *kwargs_expression=NULL) const
Definition: PY_Callback.h:130
PY_PyObject * pyObject() const noexcept