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