1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPythonAlgorithm.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkPythonAlgorithm.h"
16 #include "vtkObjectFactory.h"
17 
18 #include "vtkInformation.h"
19 #include "vtkInformationVector.h"
20 #include "vtkPythonUtil.h"
21 #include "vtkSmartPyObject.h"
22 
23 vtkStandardNewMacro(vtkPythonAlgorithm);
24 
PrintSelf(ostream & os,vtkIndent indent)25 void vtkPythonAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
26 {
27   this->Superclass::PrintSelf(os, indent);
28 
29   vtkPythonScopeGilEnsurer gilEnsurer;
30   vtkSmartPyObject str;
31   if (this->Object)
32   {
33     str.TakeReference(PyObject_Str(this->Object));
34   }
35 
36   os << indent << "Object: " << Object << std::endl;
37   if (str)
38   {
39     os << indent << "Object (string): ";
40 #ifndef VTK_PY3K
41     os << PyString_AsString(str);
42 #else
43     PyObject* bytes = PyUnicode_EncodeLocale(str, VTK_PYUNICODE_ENC);
44     if (bytes)
45     {
46       os << PyBytes_AsString(bytes);
47       Py_DECREF(bytes);
48     }
49 #endif
50     os << std::endl;
51   }
52 }
53 
vtkPythonAlgorithm()54 vtkPythonAlgorithm::vtkPythonAlgorithm()
55 {
56   this->Object = nullptr;
57 }
58 
~vtkPythonAlgorithm()59 vtkPythonAlgorithm::~vtkPythonAlgorithm()
60 {
61   // we check if Python is still initialized since the Python interpreter may
62   // have been finalized before the VTK object is released.
63   if (Py_IsInitialized())
64   {
65     vtkPythonScopeGilEnsurer gilEnsurer;
66     Py_XDECREF(this->Object);
67   }
68 }
69 
70 // This macro gets the method passed in as the parameter method
71 // from the PyObject passed in as the parameter obj and creates a
72 // vtkSmartPyObject variable with the name passed in as the parameter
73 // var containing that method's PyObject.  If obj is nullptr, obj.method
74 // does not exist or obj.method is not a callable method, this macro
75 // causes the function using it to return with the return value
76 // passed in as the parameter failValue
77 //    var - the name of the resulting vtkSmartPyObject with the
78 //          method object in it.  Can be used in the code following
79 //          the macro's use as the variable name
80 //    obj - the PyObject to get the method from
81 //    method - the name of the method to look for.  Should be a
82 //          C string.
83 //    failValue - the value to return if the lookup fails and the
84 //          function using the macro should return.  Pass in a
85 //          block comment /**/ for void functions using this macro
86 #define VTK_GET_METHOD(var, obj, method, failValue)                                                \
87   if (!(obj))                                                                                      \
88   {                                                                                                \
89     return failValue;                                                                              \
90   }                                                                                                \
91   vtkSmartPyObject var(PyObject_GetAttrString(obj, method));                                       \
92   if (!(var))                                                                                      \
93   {                                                                                                \
94     return failValue;                                                                              \
95   }                                                                                                \
96   if (!PyCallable_Check(var))                                                                      \
97   {                                                                                                \
98     return failValue;                                                                              \
99   }
100 
101 /// Return value: New reference.
VTKToPython(vtkObjectBase * obj)102 static PyObject* VTKToPython(vtkObjectBase* obj)
103 {
104   return vtkPythonUtil::GetObjectFromPointer(obj);
105 }
106 
CheckResult(const char * method,const vtkSmartPyObject & res)107 int vtkPythonAlgorithm::CheckResult(const char* method, const vtkSmartPyObject& res)
108 {
109   vtkPythonScopeGilEnsurer gilEnsurer;
110   if (!res)
111   {
112     vtkErrorMacro("Failure when calling method: \"" << method << "\":");
113     if (PyErr_Occurred() != nullptr)
114     {
115       PyErr_Print();
116       PyErr_Clear();
117     }
118     return 0;
119   }
120   if (!PyInt_Check(res))
121   {
122     return 0;
123   }
124 
125   int code = PyInt_AsLong(res);
126 
127   return code;
128 }
129 
SetPythonObject(PyObject * obj)130 void vtkPythonAlgorithm::SetPythonObject(PyObject* obj)
131 {
132   vtkPythonScopeGilEnsurer gilEnsurer;
133 
134   if (!obj)
135   {
136     return;
137   }
138 
139   Py_XDECREF(this->Object);
140 
141   this->Object = obj;
142   Py_INCREF(this->Object);
143 
144   char mname[] = "Initialize";
145   VTK_GET_METHOD(method, this->Object, mname, /* no return */)
146 
147   vtkSmartPyObject args(PyTuple_New(1));
148 
149   PyObject* vtkself = VTKToPython(this);
150   PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
151 
152   vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
153 
154   CheckResult(mname, result);
155 }
156 
SetNumberOfInputPorts(int n)157 void vtkPythonAlgorithm::SetNumberOfInputPorts(int n)
158 {
159   this->Superclass::SetNumberOfInputPorts(n);
160 }
161 
SetNumberOfOutputPorts(int n)162 void vtkPythonAlgorithm::SetNumberOfOutputPorts(int n)
163 {
164   this->Superclass::SetNumberOfOutputPorts(n);
165 }
166 
ProcessRequest(vtkInformation * request,vtkInformationVector ** inInfo,vtkInformationVector * outInfo)167 vtkTypeBool vtkPythonAlgorithm::ProcessRequest(
168   vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outInfo)
169 {
170   vtkPythonScopeGilEnsurer gilEnsurer;
171   char mname[] = "ProcessRequest";
172   VTK_GET_METHOD(method, this->Object, mname, 0)
173 
174   vtkSmartPyObject args(PyTuple_New(4));
175 
176   PyObject* vtkself = VTKToPython(this);
177   PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
178 
179   PyObject* pyrequest = VTKToPython(request);
180   PyTuple_SET_ITEM(args.GetPointer(), 1, pyrequest);
181 
182   int nports = this->GetNumberOfInputPorts();
183   PyObject* pyininfos = PyTuple_New(nports);
184   for (int i = 0; i < nports; ++i)
185   {
186     PyObject* pyininfo = VTKToPython(inInfo[i]);
187     PyTuple_SET_ITEM(pyininfos, i, pyininfo);
188   }
189   PyTuple_SET_ITEM(args.GetPointer(), 2, pyininfos);
190 
191   PyObject* pyoutinfo = VTKToPython(outInfo);
192   PyTuple_SET_ITEM(args.GetPointer(), 3, pyoutinfo);
193 
194   vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
195 
196   return CheckResult(mname, result);
197 }
198 
FillInputPortInformation(int port,vtkInformation * info)199 int vtkPythonAlgorithm::FillInputPortInformation(int port, vtkInformation* info)
200 {
201   vtkPythonScopeGilEnsurer gilEnsurer;
202   char mname[] = "FillInputPortInformation";
203   VTK_GET_METHOD(method, this->Object, mname, 0)
204 
205   vtkSmartPyObject args(PyTuple_New(3));
206 
207   PyObject* vtkself = VTKToPython(this);
208   PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
209 
210   PyObject* pyport = PyInt_FromLong(port);
211   PyTuple_SET_ITEM(args.GetPointer(), 1, pyport);
212 
213   PyObject* pyinfo = VTKToPython(info);
214   PyTuple_SET_ITEM(args.GetPointer(), 2, pyinfo);
215 
216   vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
217 
218   return CheckResult(mname, result);
219 }
220 
FillOutputPortInformation(int port,vtkInformation * info)221 int vtkPythonAlgorithm::FillOutputPortInformation(int port, vtkInformation* info)
222 {
223   vtkPythonScopeGilEnsurer gilEnsurer;
224   char mname[] = "FillOutputPortInformation";
225   VTK_GET_METHOD(method, this->Object, mname, 0)
226 
227   vtkSmartPyObject args(PyTuple_New(3));
228 
229   PyObject* vtkself = VTKToPython(this);
230   PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
231 
232   PyObject* pyport = PyInt_FromLong(port);
233   PyTuple_SET_ITEM(args.GetPointer(), 1, pyport);
234 
235   PyObject* pyinfo = VTKToPython(info);
236   PyTuple_SET_ITEM(args.GetPointer(), 2, pyinfo);
237 
238   vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
239 
240   return CheckResult(mname, result);
241 }
242