1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPythonAlgorithm.h
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 vtkSmartPyObject str;
30 if (this->Object)
31 {
32 str.TakeReference(PyObject_Str(this->Object));
33 }
34
35 os << indent << "Object: " << Object << std::endl;
36 if (str)
37 {
38 os << indent << "Object (string): " << PyString_AsString(str) << std::endl;
39 }
40 }
41
vtkPythonAlgorithm()42 vtkPythonAlgorithm::vtkPythonAlgorithm()
43 {
44 this->Object = NULL;
45 }
46
~vtkPythonAlgorithm()47 vtkPythonAlgorithm::~vtkPythonAlgorithm()
48 {
49 Py_XDECREF(this->Object);
50 }
51
52 // This macro gets the method passed in as the parameter method
53 // from the PyObject passed in as the parameter obj and creates a
54 // vtkSmartPyObject variable with the name passed in as the parameter
55 // var containing that method's PyObject. If obj is NULL, obj.method
56 // does not exist or obj.method is not a callable method, this macro
57 // causes the function using it to return with the return value
58 // passed in as the parameter failValue
59 // var - the name of the resulting vtkSmartPyObject with the
60 // method object in it. Can be used in the code following
61 // the macro's use as the variable name
62 // obj - the PyObject to get the method from
63 // method - the name of the method to look for. Should be a
64 // C string.
65 // failValue - the value to return if the lookup fails and the
66 // function using the macro should return. Pass in a
67 // block comment /**/ for void functions using this macro
68 #define VTK_GET_METHOD(var, obj, method, failValue) \
69 if (!obj) \
70 { \
71 return failValue; \
72 } \
73 vtkSmartPyObject var(PyObject_GetAttrString(obj, method)); \
74 if (!var) \
75 { \
76 return failValue; \
77 } \
78 if (!PyCallable_Check(var)) \
79 { \
80 return failValue; \
81 }
82
VTKToPython(vtkObjectBase * obj)83 static PyObject* VTKToPython(vtkObjectBase* obj)
84 {
85 return vtkPythonUtil::GetObjectFromPointer(obj);
86 }
87
GetPythonErrorString()88 static std::string GetPythonErrorString()
89 {
90 PyObject* type;
91 PyObject* value;
92 PyObject* traceback;
93
94 // Increments refcounts for returns.
95 PyErr_Fetch(&type, &value, &traceback);
96 // Put the returns in smartpointers that will
97 // automatically decrement refcounts
98 vtkSmartPyObject sType(type);
99 vtkSmartPyObject sValue(value);
100 vtkSmartPyObject sTraceback(traceback);
101
102 if (!sType)
103 {
104 return "No error from Python?!";
105 }
106
107 std::string exc_string;
108
109 vtkSmartPyObject tbModule(PyImport_ImportModule("traceback"));
110 if (tbModule)
111 {
112 vtkSmartPyObject formatFunction(PyObject_GetAttrString(tbModule.GetPointer(), "format_exception"));
113
114 vtkSmartPyObject args(PyTuple_New(3));
115
116 Py_INCREF(sType.GetPointer()); // PyTuple steals a reference.
117 PyTuple_SET_ITEM(args.GetPointer(), 0, sType.GetPointer());
118
119 Py_INCREF(sValue.GetPointer()); // PyTuple steals a reference.
120 PyTuple_SET_ITEM(args.GetPointer(), 1, sValue.GetPointer());
121
122 Py_INCREF(sTraceback.GetPointer()); // PyTuple steals a reference.
123 PyTuple_SET_ITEM(args.GetPointer(), 2, sTraceback.GetPointer());
124
125 vtkSmartPyObject formatList(PyObject_Call(formatFunction.GetPointer(), args, NULL));
126 vtkSmartPyObject fastFormatList(PySequence_Fast(formatList.GetPointer(), "format_exception didn't return a list..."));
127
128 Py_ssize_t sz = PySequence_Size(formatList.GetPointer());
129 PyObject** lst = PySequence_Fast_ITEMS(fastFormatList.GetPointer());
130 exc_string = "\n";
131 for (Py_ssize_t i = 0; i < sz; ++i)
132 {
133 PyObject* str = lst[i];
134 exc_string += PyString_AsString(str);
135 }
136 }
137 else
138 {
139 vtkSmartPyObject pyexc_string(PyObject_Str(sValue));
140 if (pyexc_string)
141 {
142 exc_string = PyString_AsString(pyexc_string);
143 }
144 else
145 {
146 exc_string = "<Unable to convert Python error to string>";
147 }
148 }
149
150 PyErr_Clear();
151
152 return exc_string;
153 }
154
CheckResult(const char * method,const vtkSmartPyObject & res)155 int vtkPythonAlgorithm::CheckResult(const char* method, const vtkSmartPyObject &res)
156 {
157 if (!res)
158 {
159 std::string pymsg = GetPythonErrorString();
160 vtkErrorMacro("Failure when calling method: \""
161 << method << "\": " << pymsg << ".");
162 return 0;
163 }
164 if (!PyInt_Check(res))
165 {
166 return 0;
167 }
168
169 int code = PyInt_AsLong(res);
170
171 return code;
172 }
173
SetPythonObject(PyObject * obj)174 void vtkPythonAlgorithm::SetPythonObject(PyObject* obj)
175 {
176 if (!obj)
177 {
178 return;
179 }
180
181 Py_XDECREF(this->Object);
182
183 this->Object = obj;
184 Py_INCREF(this->Object);
185
186 char mname[] = "Initialize";
187 VTK_GET_METHOD(method, this->Object, mname, /* no return */)
188
189 vtkSmartPyObject args(PyTuple_New(1));
190
191 PyObject* vtkself = VTKToPython(this);
192 PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
193
194 vtkSmartPyObject result(PyObject_Call(method, args, NULL));
195
196 CheckResult(mname, result);
197 }
198
SetNumberOfInputPorts(int n)199 void vtkPythonAlgorithm::SetNumberOfInputPorts(int n)
200 {
201 this->Superclass::SetNumberOfInputPorts(n);
202 }
203
SetNumberOfOutputPorts(int n)204 void vtkPythonAlgorithm::SetNumberOfOutputPorts(int n)
205 {
206 this->Superclass::SetNumberOfOutputPorts(n);
207 }
208
ProcessRequest(vtkInformation * request,vtkInformationVector ** inInfo,vtkInformationVector * outInfo)209 int vtkPythonAlgorithm::ProcessRequest(vtkInformation* request,
210 vtkInformationVector** inInfo,
211 vtkInformationVector* outInfo)
212 {
213 char mname[] = "ProcessRequest";
214 VTK_GET_METHOD(method, this->Object, mname, 0)
215
216 vtkSmartPyObject args(PyTuple_New(4));
217
218 PyObject* vtkself = VTKToPython(this);
219 PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
220
221 PyObject* pyrequest = VTKToPython(request);
222 PyTuple_SET_ITEM(args.GetPointer(), 1, pyrequest);
223
224 int nports = this->GetNumberOfInputPorts();
225 PyObject* pyininfos = PyTuple_New(nports);
226 for (int i = 0; i < nports; ++i)
227 {
228 PyObject* pyininfo = VTKToPython(inInfo[i]);
229 PyTuple_SET_ITEM(pyininfos, i, pyininfo);
230 }
231 PyTuple_SET_ITEM(args.GetPointer(), 2, pyininfos);
232
233 PyObject* pyoutinfo = VTKToPython(outInfo);
234 PyTuple_SET_ITEM(args.GetPointer(), 3, pyoutinfo);
235
236 vtkSmartPyObject result(PyObject_Call(method, args, NULL));
237
238 return CheckResult(mname, result);
239 }
240
FillInputPortInformation(int port,vtkInformation * info)241 int vtkPythonAlgorithm::FillInputPortInformation(int port, vtkInformation* info)
242 {
243 char mname[] = "FillInputPortInformation";
244 VTK_GET_METHOD(method, this->Object, mname, 0)
245
246 vtkSmartPyObject args(PyTuple_New(3));
247
248 PyObject* vtkself = VTKToPython(this);
249 PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
250
251 PyObject* pyport = PyInt_FromLong(port);
252 PyTuple_SET_ITEM(args.GetPointer(), 1, pyport);
253
254 PyObject* pyinfo = VTKToPython(info);
255 PyTuple_SET_ITEM(args.GetPointer(), 2, pyinfo);
256
257 vtkSmartPyObject result(PyObject_Call(method, args, NULL));
258
259 return CheckResult(mname, result);
260 }
261
FillOutputPortInformation(int port,vtkInformation * info)262 int vtkPythonAlgorithm::FillOutputPortInformation(int port, vtkInformation* info)
263 {
264 char mname[] = "FillOutputPortInformation";
265 VTK_GET_METHOD(method, this->Object, mname, 0)
266
267 vtkSmartPyObject args(PyTuple_New(3));
268
269 PyObject* vtkself = VTKToPython(this);
270 PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
271
272 PyObject* pyport = PyInt_FromLong(port);
273 PyTuple_SET_ITEM(args.GetPointer(), 1, pyport);
274
275 PyObject* pyinfo = VTKToPython(info);
276 PyTuple_SET_ITEM(args.GetPointer(), 2, pyinfo);
277
278 vtkSmartPyObject result(PyObject_Call(method, args, NULL));
279
280 return CheckResult(mname, result);
281 }
282