fazekasgy@37
|
1 /*
|
fazekasgy@37
|
2
|
fazekasgy@37
|
3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
|
fazekasgy@37
|
4 * It allows for writing Vamp plugins in Python.
|
fazekasgy@37
|
5
|
fazekasgy@37
|
6 * Centre for Digital Music, Queen Mary University of London.
|
fazekasgy@37
|
7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
|
fazekasgy@37
|
8 * for licence information.)
|
fazekasgy@37
|
9
|
fazekasgy@37
|
10 */
|
fazekasgy@37
|
11
|
fazekasgy@37
|
12 #ifndef _PYTHON_WRAPPER_PLUGIN_H_
|
fazekasgy@37
|
13 #define _PYTHON_WRAPPER_PLUGIN_H_
|
fazekasgy@37
|
14
|
fazekasgy@37
|
15 #define _CLASS_METHOD_ m_class << "::" << method
|
fazekasgy@37
|
16 #define PLUGIN_ERROR "ERROR: In Vampy plugin [" << _CLASS_METHOD_ << "]" << endl << "Cause: "
|
fazekasgy@37
|
17 #define DEBUG_NAME "[Vampy::call] " << _CLASS_METHOD_ << " "
|
Chris@67
|
18 #define DEFAULT_RETURN "Method [" << _CLASS_METHOD_ << "] is not implemented. Returning default value."
|
fazekasgy@37
|
19 #define FLAG_VALUE "Flag: " << flagName << ": " << ((rValue==0)?"False":"True")
|
fazekasgy@37
|
20
|
fazekasgy@37
|
21 #include <Python.h>
|
fazekasgy@37
|
22 #include "PyExtensionModule.h"
|
fazekasgy@37
|
23 #include "PyTypeInterface.h"
|
Chris@71
|
24 #include "PyTypeConversions.h"
|
fazekasgy@37
|
25 #include "vamp-sdk/Plugin.h"
|
fazekasgy@37
|
26 #include "Mutex.h"
|
fazekasgy@37
|
27
|
fazekasgy@37
|
28 using std::string;
|
fazekasgy@37
|
29 using std::cerr;
|
fazekasgy@37
|
30 using std::endl;
|
fazekasgy@37
|
31
|
fazekasgy@37
|
32 enum eProcessType {
|
fazekasgy@37
|
33 not_implemented,
|
fazekasgy@37
|
34 legacyProcess,
|
fazekasgy@37
|
35 numpyProcess,
|
fazekasgy@37
|
36 numpy_bufferProcess,
|
fazekasgy@37
|
37 numpy_arrayProcess
|
fazekasgy@37
|
38 };
|
fazekasgy@37
|
39
|
fazekasgy@37
|
40 class PyPlugin : public Vamp::Plugin
|
fazekasgy@37
|
41 {
|
fazekasgy@37
|
42 public:
|
fazekasgy@51
|
43 PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass, int &instcount, bool &numpyInstalled);
|
fazekasgy@37
|
44 virtual ~PyPlugin();
|
fazekasgy@37
|
45
|
fazekasgy@37
|
46 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
fazekasgy@37
|
47 void reset();
|
fazekasgy@37
|
48
|
fazekasgy@37
|
49 InputDomain getInputDomain() const;
|
fazekasgy@37
|
50 size_t getPreferredBlockSize() const;
|
fazekasgy@37
|
51 size_t getPreferredStepSize() const;
|
fazekasgy@37
|
52 size_t getMinChannelCount() const;
|
fazekasgy@37
|
53 size_t getMaxChannelCount() const;
|
fazekasgy@37
|
54
|
fazekasgy@37
|
55 std::string getIdentifier() const;
|
fazekasgy@37
|
56 std::string getName() const;
|
fazekasgy@37
|
57 std::string getDescription() const;
|
fazekasgy@37
|
58 std::string getMaker() const;
|
fazekasgy@37
|
59 int getPluginVersion() const;
|
fazekasgy@37
|
60 std::string getCopyright() const;
|
fazekasgy@37
|
61
|
fazekasgy@37
|
62 OutputList getOutputDescriptors() const;
|
fazekasgy@37
|
63 ParameterList getParameterDescriptors() const;
|
fazekasgy@37
|
64 float getParameter(std::string paramid) const;
|
fazekasgy@37
|
65 void setParameter(std::string paramid, float newval);
|
fazekasgy@37
|
66
|
fazekasgy@37
|
67 FeatureSet process(const float *const *inputBuffers,
|
fazekasgy@37
|
68 Vamp::RealTime timestamp);
|
fazekasgy@37
|
69
|
fazekasgy@37
|
70 FeatureSet getRemainingFeatures();
|
fazekasgy@37
|
71
|
fazekasgy@37
|
72 protected:
|
fazekasgy@37
|
73 static Mutex m_pythonInterpreterMutex;
|
fazekasgy@37
|
74 PyObject *m_pyClass;
|
fazekasgy@37
|
75 PyObject *m_pyInstance;
|
fazekasgy@37
|
76 int &m_instcount;
|
fazekasgy@37
|
77 size_t m_stepSize;
|
fazekasgy@37
|
78 size_t m_blockSize;
|
fazekasgy@37
|
79 size_t m_channels;
|
fazekasgy@37
|
80 std::string m_plugin;
|
fazekasgy@37
|
81 std::string m_class;
|
fazekasgy@37
|
82 std::string m_path;
|
fazekasgy@37
|
83 eProcessType m_processType;
|
fazekasgy@37
|
84 PyObject *m_pyProcess;
|
fazekasgy@37
|
85 PyObject *m_pyProcessCallable;
|
fazekasgy@37
|
86 mutable InputDomain m_inputDomain;
|
Chris@71
|
87 PyTypeConversions m_tc;
|
fazekasgy@37
|
88 PyTypeInterface m_ti;
|
fazekasgy@37
|
89 int m_vampyFlags;
|
fazekasgy@37
|
90 bool m_quitOnErrorFlag;
|
fazekasgy@37
|
91 bool m_debugFlag;
|
fazekasgy@37
|
92 bool m_useRealTimeFlag;
|
fazekasgy@51
|
93 bool m_numpyInstalled;
|
fazekasgy@51
|
94 mutable bool m_processFailure;
|
fazekasgy@37
|
95
|
fazekasgy@37
|
96 void setProcessType();
|
fazekasgy@37
|
97
|
fazekasgy@37
|
98 FeatureSet processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp);
|
fazekasgy@37
|
99
|
Chris@66
|
100 bool getBooleanFlag(const char flagName[],bool) const;
|
Chris@66
|
101 int getBinaryFlags(const char flagName[], eVampyFlags) const;
|
Chris@66
|
102 void typeErrorHandler(const char *method, bool process = false) const;
|
fazekasgy@37
|
103
|
fazekasgy@37
|
104 /// simple 'void return' call with no args
|
Chris@66
|
105 void genericMethodCall(const char *method) const
|
fazekasgy@37
|
106 {
|
fazekasgy@37
|
107 if (m_debugFlag) cerr << DEBUG_NAME << endl;
|
fazekasgy@37
|
108 if ( PyObject_HasAttrString(m_pyInstance,method) )
|
fazekasgy@37
|
109 {
|
Chris@66
|
110 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
|
fazekasgy@37
|
111 if (!pyValue) {
|
fazekasgy@37
|
112 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
|
fazekasgy@37
|
113 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
114 }
|
fazekasgy@37
|
115 }
|
fazekasgy@37
|
116 }
|
fazekasgy@37
|
117
|
fazekasgy@37
|
118 /// 'no arg with default return value' call
|
fazekasgy@37
|
119 template<typename RET>
|
Chris@66
|
120 RET &genericMethodCall(const char *method, RET &rValue) const
|
fazekasgy@37
|
121 {
|
fazekasgy@37
|
122 if (m_debugFlag) cerr << DEBUG_NAME << endl;
|
fazekasgy@37
|
123 if ( PyObject_HasAttrString(m_pyInstance,method) )
|
fazekasgy@37
|
124 {
|
Chris@66
|
125 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
|
fazekasgy@37
|
126 if (!pyValue) {
|
fazekasgy@37
|
127 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
|
fazekasgy@37
|
128 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
129 return rValue;
|
fazekasgy@37
|
130 }
|
fazekasgy@37
|
131
|
fazekasgy@37
|
132 /// convert the returned value
|
fazekasgy@37
|
133 m_ti.PyValue_To_rValue(pyValue,rValue);
|
fazekasgy@37
|
134 if (!m_ti.error) {
|
fazekasgy@37
|
135 Py_DECREF(pyValue);
|
fazekasgy@37
|
136 } else {
|
fazekasgy@37
|
137 Py_CLEAR(pyValue);
|
fazekasgy@37
|
138 typeErrorHandler(method);
|
fazekasgy@37
|
139 }
|
fazekasgy@37
|
140 return rValue;
|
fazekasgy@37
|
141 }
|
Chris@67
|
142 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
|
fazekasgy@37
|
143 return rValue;
|
fazekasgy@37
|
144 }
|
fazekasgy@37
|
145
|
fazekasgy@37
|
146 /// unary call
|
fazekasgy@37
|
147 template<typename RET,typename A1>
|
Chris@66
|
148 RET genericMethodCallArgs(const char *method, A1 arg1) const
|
fazekasgy@37
|
149 {
|
fazekasgy@37
|
150 RET rValue = RET();
|
fazekasgy@37
|
151 if (m_debugFlag) cerr << DEBUG_NAME << endl;
|
fazekasgy@37
|
152 if (!PyObject_HasAttrString(m_pyInstance,method)) {
|
Chris@67
|
153 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
|
fazekasgy@37
|
154 return rValue;
|
fazekasgy@37
|
155 }
|
fazekasgy@37
|
156
|
fazekasgy@37
|
157 /// prepare arguments for fast method call
|
Chris@71
|
158 PyObject *pyMethod = m_tc.PyValue_From_CValue(method);
|
fazekasgy@37
|
159 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
|
fazekasgy@37
|
160 PyObject* pyArgs = PyTuple_New(1);
|
fazekasgy@37
|
161 if (!(pyArgs && pyCallable && pyMethod)) {
|
fazekasgy@37
|
162 cerr << PLUGIN_ERROR << "Failed to prepare argument for calling method." << endl;
|
fazekasgy@37
|
163 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
164 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
165 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
166 return rValue;
|
fazekasgy@37
|
167 }
|
fazekasgy@37
|
168
|
Chris@71
|
169 PyObject *pyArg1 = m_tc.PyValue_From_CValue(arg1);
|
Chris@71
|
170 if (m_tc.error) {
|
fazekasgy@37
|
171 cerr << PLUGIN_ERROR << "Failed to convert argument for calling method." << endl;
|
fazekasgy@37
|
172 typeErrorHandler(method);
|
fazekasgy@37
|
173 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
174 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
175 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
176 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
177 return rValue;
|
fazekasgy@37
|
178 }
|
fazekasgy@37
|
179
|
fazekasgy@37
|
180 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
|
fazekasgy@37
|
181 Py_INCREF(pyArg1);
|
fazekasgy@37
|
182
|
fazekasgy@37
|
183 /// call the method
|
fazekasgy@37
|
184 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
|
fazekasgy@37
|
185 if (!pyValue)
|
fazekasgy@37
|
186 {
|
fazekasgy@37
|
187 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
|
fazekasgy@37
|
188 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
189 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
190 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
191 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
192 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
193 return rValue;
|
fazekasgy@37
|
194 }
|
fazekasgy@37
|
195
|
fazekasgy@37
|
196 Py_DECREF(pyMethod);
|
fazekasgy@37
|
197 Py_DECREF(pyCallable);
|
fazekasgy@37
|
198 Py_DECREF(pyArg1);
|
fazekasgy@37
|
199 Py_DECREF(pyArgs);
|
fazekasgy@37
|
200
|
fazekasgy@37
|
201 /// convert the returned value
|
fazekasgy@37
|
202 m_ti.PyValue_To_rValue(pyValue,rValue);
|
fazekasgy@37
|
203 if (!m_ti.error) {
|
fazekasgy@37
|
204 Py_DECREF(pyValue);
|
fazekasgy@37
|
205 } else {
|
fazekasgy@37
|
206 Py_CLEAR(pyValue);
|
fazekasgy@37
|
207 typeErrorHandler(method);
|
fazekasgy@37
|
208 }
|
fazekasgy@37
|
209 return rValue;
|
fazekasgy@37
|
210 }
|
fazekasgy@37
|
211
|
fazekasgy@37
|
212 /// binary call
|
fazekasgy@37
|
213 template<typename RET,typename A1,typename A2>
|
Chris@66
|
214 RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2) const
|
fazekasgy@37
|
215 {
|
fazekasgy@37
|
216 RET rValue = RET();
|
fazekasgy@37
|
217 if (m_debugFlag) cerr << DEBUG_NAME << endl;
|
fazekasgy@37
|
218 if (!PyObject_HasAttrString(m_pyInstance,method)) {
|
Chris@67
|
219 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
|
fazekasgy@37
|
220 return rValue;
|
fazekasgy@37
|
221 }
|
fazekasgy@37
|
222
|
fazekasgy@37
|
223 /// prepare arguments for fast method call
|
Chris@71
|
224 PyObject *pyMethod = m_tc.PyValue_From_CValue(method);
|
fazekasgy@37
|
225 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
|
fazekasgy@37
|
226 PyObject* pyArgs = PyTuple_New(2);
|
fazekasgy@37
|
227 if (!(pyArgs && pyCallable && pyMethod)) {
|
fazekasgy@37
|
228 cerr << PLUGIN_ERROR << "Failed to prepare arguments for calling method." << endl;
|
fazekasgy@37
|
229 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
230 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
231 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
232 return rValue;
|
fazekasgy@37
|
233 }
|
fazekasgy@37
|
234
|
Chris@71
|
235 PyObject *pyArg1 = m_tc.PyValue_From_CValue(arg1);
|
Chris@71
|
236 PyObject *pyArg2 = m_tc.PyValue_From_CValue(arg2);
|
Chris@71
|
237 if (m_tc.error) {
|
fazekasgy@37
|
238 cerr << PLUGIN_ERROR << "Failed to convert arguments for calling method." << endl;
|
fazekasgy@37
|
239 typeErrorHandler(method);
|
fazekasgy@37
|
240 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
241 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
242 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
243 Py_CLEAR(pyArg2);
|
fazekasgy@37
|
244 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
245 return rValue;
|
fazekasgy@37
|
246 }
|
fazekasgy@37
|
247
|
fazekasgy@37
|
248 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
|
fazekasgy@37
|
249 Py_INCREF(pyArg1);
|
fazekasgy@37
|
250 PyTuple_SET_ITEM(pyArgs, 1, pyArg2);
|
fazekasgy@37
|
251 Py_INCREF(pyArg2);
|
fazekasgy@37
|
252
|
fazekasgy@37
|
253 // calls the method
|
fazekasgy@37
|
254 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
|
fazekasgy@37
|
255 if (!pyValue)
|
fazekasgy@37
|
256 {
|
fazekasgy@37
|
257 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
|
fazekasgy@37
|
258 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
259 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
260 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
261 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
262 Py_CLEAR(pyArg2);
|
fazekasgy@37
|
263 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
264 return rValue;
|
fazekasgy@37
|
265 }
|
fazekasgy@37
|
266
|
fazekasgy@37
|
267 Py_DECREF(pyMethod);
|
fazekasgy@37
|
268 Py_DECREF(pyCallable);
|
fazekasgy@37
|
269 Py_DECREF(pyArg1);
|
fazekasgy@37
|
270 Py_DECREF(pyArg2);
|
fazekasgy@37
|
271 Py_DECREF(pyArgs);
|
fazekasgy@37
|
272
|
fazekasgy@37
|
273 /// convert the returned value
|
fazekasgy@37
|
274 m_ti.PyValue_To_rValue(pyValue,rValue);
|
fazekasgy@37
|
275 if (!m_ti.error) {
|
fazekasgy@37
|
276 Py_DECREF(pyValue);
|
fazekasgy@37
|
277 } else {
|
fazekasgy@37
|
278 Py_CLEAR(pyValue);
|
fazekasgy@37
|
279 typeErrorHandler(method);
|
fazekasgy@37
|
280 }
|
fazekasgy@37
|
281 return rValue;
|
fazekasgy@37
|
282 }
|
fazekasgy@37
|
283
|
fazekasgy@37
|
284 /// trenary call
|
fazekasgy@37
|
285 template<typename RET,typename A1,typename A2,typename A3>
|
Chris@66
|
286 RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2, A3 arg3) const
|
fazekasgy@37
|
287 {
|
fazekasgy@37
|
288 RET rValue = RET();
|
fazekasgy@37
|
289 if (m_debugFlag) cerr << DEBUG_NAME << endl;
|
fazekasgy@37
|
290 if (!PyObject_HasAttrString(m_pyInstance,method)) {
|
Chris@67
|
291 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
|
fazekasgy@37
|
292 return rValue;
|
fazekasgy@37
|
293 }
|
fazekasgy@37
|
294
|
fazekasgy@37
|
295 /// prepare arguments for fast method call
|
Chris@71
|
296 PyObject *pyMethod = m_tc.PyValue_From_CValue(method);
|
fazekasgy@37
|
297 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
|
fazekasgy@37
|
298 PyObject* pyArgs = PyTuple_New(3);
|
fazekasgy@37
|
299 if (!(pyArgs && pyCallable && pyMethod)) {
|
fazekasgy@37
|
300 cerr << PLUGIN_ERROR << "Failed to prepare arguments for calling method." << endl;
|
fazekasgy@37
|
301 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
302 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
303 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
304 return rValue;
|
fazekasgy@37
|
305 }
|
fazekasgy@37
|
306
|
Chris@71
|
307 PyObject *pyArg1 = m_tc.PyValue_From_CValue(arg1);
|
Chris@71
|
308 PyObject *pyArg2 = m_tc.PyValue_From_CValue(arg2);
|
Chris@71
|
309 PyObject *pyArg3 = m_tc.PyValue_From_CValue(arg3);
|
Chris@71
|
310 if (m_tc.error) {
|
fazekasgy@37
|
311 cerr << PLUGIN_ERROR << "Failed to convert arguments for calling method." << endl;
|
fazekasgy@37
|
312 typeErrorHandler(method);
|
fazekasgy@37
|
313 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
314 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
315 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
316 Py_CLEAR(pyArg2);
|
fazekasgy@37
|
317 Py_CLEAR(pyArg3);
|
fazekasgy@37
|
318 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
319 return rValue;
|
fazekasgy@37
|
320 }
|
fazekasgy@37
|
321
|
fazekasgy@37
|
322 /// Optimization: Pack args in a tuple to avoid va_list parsing.
|
fazekasgy@37
|
323 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
|
fazekasgy@37
|
324 Py_INCREF(pyArg1);
|
fazekasgy@37
|
325 PyTuple_SET_ITEM(pyArgs, 1, pyArg2);
|
fazekasgy@37
|
326 Py_INCREF(pyArg2);
|
fazekasgy@37
|
327 PyTuple_SET_ITEM(pyArgs, 2, pyArg3);
|
fazekasgy@37
|
328 Py_INCREF(pyArg3);
|
fazekasgy@37
|
329
|
fazekasgy@37
|
330 // PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,pyArg3,NULL);
|
fazekasgy@37
|
331 /// fast method call
|
fazekasgy@37
|
332 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
|
fazekasgy@37
|
333 if (!pyValue)
|
fazekasgy@37
|
334 {
|
fazekasgy@37
|
335 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
|
fazekasgy@37
|
336 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
337 Py_CLEAR(pyMethod);
|
fazekasgy@37
|
338 Py_CLEAR(pyCallable);
|
fazekasgy@37
|
339 Py_CLEAR(pyArg1);
|
fazekasgy@37
|
340 Py_CLEAR(pyArg2);
|
fazekasgy@37
|
341 Py_CLEAR(pyArg3);
|
fazekasgy@37
|
342 Py_CLEAR(pyArgs);
|
fazekasgy@37
|
343 return rValue;
|
fazekasgy@37
|
344 }
|
fazekasgy@37
|
345
|
fazekasgy@37
|
346 Py_DECREF(pyMethod);
|
fazekasgy@37
|
347 Py_DECREF(pyCallable);
|
fazekasgy@37
|
348 Py_DECREF(pyArg1);
|
fazekasgy@37
|
349 Py_DECREF(pyArg2);
|
fazekasgy@37
|
350 Py_DECREF(pyArg3);
|
fazekasgy@37
|
351 Py_DECREF(pyArgs);
|
fazekasgy@37
|
352
|
fazekasgy@37
|
353 /// convert the returned value
|
fazekasgy@37
|
354 m_ti.PyValue_To_rValue(pyValue,rValue);
|
fazekasgy@37
|
355 if (!m_ti.error) {
|
fazekasgy@37
|
356 Py_DECREF(pyValue);
|
fazekasgy@37
|
357 } else {
|
fazekasgy@37
|
358 Py_CLEAR(pyValue);
|
fazekasgy@37
|
359 typeErrorHandler(method);
|
fazekasgy@37
|
360 }
|
fazekasgy@37
|
361 return rValue;
|
fazekasgy@37
|
362 }
|
fazekasgy@37
|
363
|
fazekasgy@37
|
364 };
|
fazekasgy@37
|
365
|
fazekasgy@37
|
366 #endif
|