Chris@26
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@26
|
2
|
Chris@26
|
3 /*
|
Chris@26
|
4 VampyHost
|
Chris@26
|
5
|
Chris@26
|
6 Use Vamp audio analysis plugins in Python
|
Chris@26
|
7
|
Chris@26
|
8 Gyorgy Fazekas and Chris Cannam
|
Chris@26
|
9 Centre for Digital Music, Queen Mary, University of London
|
Chris@26
|
10 Copyright 2008-2014 Queen Mary, University of London
|
Chris@26
|
11
|
Chris@26
|
12 Permission is hereby granted, free of charge, to any person
|
Chris@26
|
13 obtaining a copy of this software and associated documentation
|
Chris@26
|
14 files (the "Software"), to deal in the Software without
|
Chris@26
|
15 restriction, including without limitation the rights to use, copy,
|
Chris@26
|
16 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@26
|
17 of the Software, and to permit persons to whom the Software is
|
Chris@26
|
18 furnished to do so, subject to the following conditions:
|
Chris@26
|
19
|
Chris@26
|
20 The above copyright notice and this permission notice shall be
|
Chris@26
|
21 included in all copies or substantial portions of the Software.
|
Chris@26
|
22
|
Chris@26
|
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@26
|
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@26
|
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@26
|
26 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
Chris@26
|
27 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@26
|
28 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@26
|
29 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@26
|
30
|
Chris@26
|
31 Except as contained in this notice, the names of the Centre for
|
Chris@26
|
32 Digital Music; Queen Mary, University of London; and the authors
|
Chris@26
|
33 shall not be used in advertising or otherwise to promote the sale,
|
Chris@26
|
34 use or other dealings in this Software without prior written
|
Chris@26
|
35 authorization.
|
Chris@26
|
36 */
|
Chris@26
|
37
|
Chris@26
|
38 #include <Python.h>
|
Chris@26
|
39
|
Chris@26
|
40 #include "PyTypeConversions.h"
|
Chris@26
|
41
|
Chris@26
|
42 #include <math.h>
|
Chris@26
|
43 #include <float.h>
|
Chris@26
|
44 #include <limits.h>
|
Chris@26
|
45 #ifndef SIZE_T_MAX
|
Chris@26
|
46 #define SIZE_T_MAX ((size_t) -1)
|
Chris@26
|
47 #endif
|
Chris@26
|
48
|
Chris@26
|
49 using std::string;
|
Chris@26
|
50 using std::vector;
|
Chris@26
|
51 using std::cerr;
|
Chris@26
|
52 using std::endl;
|
Chris@26
|
53
|
Chris@26
|
54 /* Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
|
Chris@26
|
55 (EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
|
Chris@26
|
56
|
Chris@26
|
57 PyTypeConversions::PyTypeConversions() :
|
Chris@26
|
58 m_strict(false),
|
Chris@26
|
59 m_error(false),
|
Chris@26
|
60 m_numpyInstalled(false),
|
Chris@26
|
61 error(m_error) // const public reference for easy access
|
Chris@26
|
62 {
|
Chris@26
|
63 }
|
Chris@26
|
64
|
Chris@26
|
65 PyTypeConversions::~PyTypeConversions()
|
Chris@26
|
66 {
|
Chris@26
|
67 }
|
Chris@26
|
68
|
Chris@26
|
69 /// floating point numbers (TODO: check numpy.float128)
|
Chris@26
|
70 float
|
Chris@26
|
71 PyTypeConversions::PyValue_To_Float(PyObject* pyValue) const
|
Chris@26
|
72 {
|
Chris@26
|
73 // convert float
|
Chris@26
|
74 if (pyValue && PyFloat_Check(pyValue))
|
Chris@26
|
75 //TODO: check for limits here (same on most systems)
|
Chris@26
|
76 return (float) PyFloat_AS_DOUBLE(pyValue);
|
Chris@26
|
77
|
Chris@26
|
78 if (pyValue == NULL)
|
Chris@26
|
79 {
|
Chris@26
|
80 setValueError("Error while converting object " + PyValue_Get_TypeName(pyValue) + " to float. ",m_strict);
|
Chris@26
|
81 return 0.0;
|
Chris@26
|
82 }
|
Chris@26
|
83
|
Chris@26
|
84 // in strict mode we will not try harder
|
Chris@26
|
85 if (m_strict) {
|
Chris@26
|
86 setValueError("Strict conversion error: object" + PyValue_Get_TypeName(pyValue) +" is not float.",m_strict);
|
Chris@26
|
87 return 0.0;
|
Chris@26
|
88 }
|
Chris@26
|
89
|
Chris@26
|
90 // convert other objects supporting the number protocol
|
Chris@26
|
91 if (PyNumber_Check(pyValue))
|
Chris@26
|
92 {
|
Chris@26
|
93 PyObject* pyFloat = PyNumber_Float(pyValue); // new ref
|
Chris@26
|
94 if (!pyFloat)
|
Chris@26
|
95 {
|
Chris@26
|
96 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
97 setValueError("Error while converting " + PyValue_Get_TypeName(pyValue) + " object to float.",m_strict);
|
Chris@26
|
98 return 0.0;
|
Chris@26
|
99 }
|
Chris@26
|
100 float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
Chris@26
|
101 Py_DECREF(pyFloat);
|
Chris@26
|
102 return rValue;
|
Chris@26
|
103 }
|
Chris@26
|
104 /*
|
Chris@26
|
105 // convert other objects supporting the number protocol
|
Chris@26
|
106 if (PyNumber_Check(pyValue))
|
Chris@26
|
107 {
|
Chris@26
|
108 // PEP353: Py_ssize_t is size_t but signed !
|
Chris@26
|
109 // This will work up to numpy.float64
|
Chris@26
|
110 Py_ssize_t rValue = PyNumber_AsSsize_t(pyValue,NULL);
|
Chris@26
|
111 if (PyErr_Occurred())
|
Chris@26
|
112 {
|
Chris@26
|
113 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
114 setValueError("Error while converting integer object.",m_strict);
|
Chris@26
|
115 return 0.0;
|
Chris@26
|
116 }
|
Chris@26
|
117 if (rValue > (Py_ssize_t)FLT_MAX || rValue < (Py_ssize_t)FLT_MIN)
|
Chris@26
|
118 {
|
Chris@26
|
119 setValueError("Overflow error. Object can not be converted to float.",m_strict);
|
Chris@26
|
120 return 0.0;
|
Chris@26
|
121 }
|
Chris@26
|
122 return (float) rValue;
|
Chris@26
|
123 }
|
Chris@26
|
124 */
|
Chris@26
|
125 // convert string
|
Chris@26
|
126 if (PyString_Check(pyValue))
|
Chris@26
|
127 {
|
Chris@26
|
128 PyObject* pyFloat = PyFloat_FromString(pyValue,NULL);
|
Chris@26
|
129 if (!pyFloat)
|
Chris@26
|
130 {
|
Chris@26
|
131 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
132 setValueError("String value can not be converted to float.",m_strict);
|
Chris@26
|
133 return 0.0;
|
Chris@26
|
134 }
|
Chris@26
|
135 float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
Chris@26
|
136 if (PyErr_Occurred())
|
Chris@26
|
137 {
|
Chris@26
|
138 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
139 Py_CLEAR(pyFloat);
|
Chris@26
|
140 setValueError("Error while converting float object.",m_strict);
|
Chris@26
|
141 return 0.0;
|
Chris@26
|
142 }
|
Chris@26
|
143 Py_DECREF(pyFloat);
|
Chris@26
|
144 return rValue;
|
Chris@26
|
145 }
|
Chris@26
|
146
|
Chris@26
|
147 // convert the first element of any iterable sequence (for convenience and backwards compatibility)
|
Chris@26
|
148 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
Chris@26
|
149 {
|
Chris@26
|
150 PyObject* item = PySequence_GetItem(pyValue,0);
|
Chris@26
|
151 if (item)
|
Chris@26
|
152 {
|
Chris@26
|
153 float rValue = this->PyValue_To_Float(item);
|
Chris@26
|
154 if (!m_error) {
|
Chris@26
|
155 Py_DECREF(item);
|
Chris@26
|
156 return rValue;
|
Chris@26
|
157 } else {
|
Chris@26
|
158 Py_CLEAR(item);
|
Chris@26
|
159 std::string msg = "Could not convert sequence element to float. ";
|
Chris@26
|
160 setValueError(msg,m_strict);
|
Chris@26
|
161 return 0.0;
|
Chris@26
|
162 }
|
Chris@26
|
163 }
|
Chris@26
|
164 }
|
Chris@26
|
165
|
Chris@26
|
166 // give up
|
Chris@26
|
167 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
168 std::string msg = "Conversion from " + PyValue_Get_TypeName(pyValue) + " to float is not possible.";
|
Chris@26
|
169 setValueError(msg,m_strict);
|
Chris@26
|
170 #ifdef _DEBUG
|
Chris@26
|
171 cerr << "PyTypeConversions::PyValue_To_Float failed. " << msg << endl;
|
Chris@26
|
172 #endif
|
Chris@26
|
173 return 0.0;
|
Chris@26
|
174 }
|
Chris@26
|
175
|
Chris@26
|
176 /// size_t (unsigned integer types)
|
Chris@26
|
177 size_t
|
Chris@26
|
178 PyTypeConversions::PyValue_To_Size_t(PyObject* pyValue) const
|
Chris@26
|
179 {
|
Chris@26
|
180 // convert objects supporting the number protocol
|
Chris@26
|
181 if (PyNumber_Check(pyValue))
|
Chris@26
|
182 {
|
Chris@26
|
183 if (m_strict && !PyInt_Check(pyValue) && !PyLong_Check(pyValue))
|
Chris@26
|
184 setValueError("Strict conversion error: object is not integer type.",m_strict);
|
Chris@26
|
185 // Note: this function handles Bool,Int,Long,Float
|
Chris@26
|
186 // speed is not critical in the use of this type by Vamp
|
Chris@26
|
187 // PEP353: Py_ssize_t is size_t but signed !
|
Chris@26
|
188 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
Chris@26
|
189 if (PyErr_Occurred())
|
Chris@26
|
190 {
|
Chris@26
|
191 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
192 setValueError("Error while converting integer object.",m_strict);
|
Chris@26
|
193 return 0;
|
Chris@26
|
194 }
|
Chris@26
|
195 // this test is nonsense -- neither part can occur
|
Chris@26
|
196 // owing to range of data types -- size_t is at least
|
Chris@26
|
197 // as big as long, and unsigned is always non-negative
|
Chris@26
|
198 /*
|
Chris@26
|
199 if ((unsigned long)rValue > SIZE_T_MAX || (unsigned long)rValue < 0)
|
Chris@26
|
200 {
|
Chris@26
|
201 setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
|
Chris@26
|
202 return 0;
|
Chris@26
|
203 }
|
Chris@26
|
204 */
|
Chris@26
|
205 return (size_t) rValue;
|
Chris@26
|
206 }
|
Chris@26
|
207
|
Chris@26
|
208 // in strict mode we will not try harder and throw an exception
|
Chris@26
|
209 // then the caller should decide what to do with it
|
Chris@26
|
210 if (m_strict) {
|
Chris@26
|
211 setValueError("Strict conversion error: object is not integer.",m_strict);
|
Chris@26
|
212 return 0;
|
Chris@26
|
213 }
|
Chris@26
|
214
|
Chris@26
|
215 // convert string
|
Chris@26
|
216 if (PyString_Check(pyValue))
|
Chris@26
|
217 {
|
Chris@26
|
218 PyObject* pyLong = PyNumber_Long(pyValue);
|
Chris@26
|
219 if (!pyLong)
|
Chris@26
|
220 {
|
Chris@26
|
221 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
222 setValueError("String object can not be converted to size_t.",m_strict);
|
Chris@26
|
223 return 0;
|
Chris@26
|
224 }
|
Chris@26
|
225 size_t rValue = this->PyValue_To_Size_t(pyLong);
|
Chris@26
|
226 if (!m_error) {
|
Chris@26
|
227 Py_DECREF(pyLong);
|
Chris@26
|
228 return rValue;
|
Chris@26
|
229 } else {
|
Chris@26
|
230 Py_CLEAR(pyLong);
|
Chris@26
|
231 setValueError ("Error converting string to size_t.",m_strict);
|
Chris@26
|
232 return 0;
|
Chris@26
|
233 }
|
Chris@26
|
234 }
|
Chris@26
|
235
|
Chris@26
|
236 // convert the first element of iterable sequences
|
Chris@26
|
237 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
Chris@26
|
238 {
|
Chris@26
|
239 PyObject* item = PySequence_GetItem(pyValue,0);
|
Chris@26
|
240 if (item)
|
Chris@26
|
241 {
|
Chris@26
|
242 size_t rValue = this->PyValue_To_Size_t(item);
|
Chris@26
|
243 if (!m_error) {
|
Chris@26
|
244 Py_DECREF(item);
|
Chris@26
|
245 return rValue;
|
Chris@26
|
246 } else {
|
Chris@26
|
247 Py_CLEAR(item);
|
Chris@26
|
248 setValueError("Could not convert sequence element to size_t. ",m_strict);
|
Chris@26
|
249 return 0;
|
Chris@26
|
250 }
|
Chris@26
|
251 }
|
Chris@26
|
252 }
|
Chris@26
|
253
|
Chris@26
|
254 // give up
|
Chris@26
|
255 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
256 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to size_t is not possible.";
|
Chris@26
|
257 setValueError(msg,m_strict);
|
Chris@26
|
258 #ifdef _DEBUG
|
Chris@26
|
259 cerr << "PyTypeConversions::PyValue_To_Size_t failed. " << msg << endl;
|
Chris@26
|
260 #endif
|
Chris@26
|
261 return 0;
|
Chris@26
|
262 }
|
Chris@26
|
263
|
Chris@26
|
264 /// long and int
|
Chris@26
|
265 long
|
Chris@26
|
266 PyTypeConversions::PyValue_To_Long(PyObject* pyValue) const
|
Chris@26
|
267 {
|
Chris@26
|
268 // most common case: convert int (faster)
|
Chris@26
|
269 if (pyValue && PyInt_Check(pyValue)) {
|
Chris@26
|
270 // if the object is not NULL and verified, this macro just extracts the value.
|
Chris@26
|
271 return PyInt_AS_LONG(pyValue);
|
Chris@26
|
272 }
|
Chris@26
|
273
|
Chris@26
|
274 // long
|
Chris@26
|
275 if (PyLong_Check(pyValue)) {
|
Chris@26
|
276 long rValue = PyLong_AsLong(pyValue);
|
Chris@26
|
277 if (PyErr_Occurred()) {
|
Chris@26
|
278 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
279 setValueError("Error while converting long object.",m_strict);
|
Chris@26
|
280 return 0;
|
Chris@26
|
281 }
|
Chris@26
|
282 return rValue;
|
Chris@26
|
283 }
|
Chris@26
|
284
|
Chris@26
|
285 if (m_strict) {
|
Chris@26
|
286 setValueError("Strict conversion error: object is not integer or long integer.",m_strict);
|
Chris@26
|
287 return 0;
|
Chris@26
|
288 }
|
Chris@26
|
289
|
Chris@26
|
290 // convert all objects supporting the number protocol
|
Chris@26
|
291 if (PyNumber_Check(pyValue))
|
Chris@26
|
292 {
|
Chris@26
|
293 // Note: this function handles Bool,Int,Long,Float
|
Chris@26
|
294 // PEP353: Py_ssize_t is size_t but signed !
|
Chris@26
|
295 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
Chris@26
|
296 if (PyErr_Occurred())
|
Chris@26
|
297 {
|
Chris@26
|
298 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
299 setValueError("Error while converting integer object.",m_strict);
|
Chris@26
|
300 return 0;
|
Chris@26
|
301 }
|
Chris@26
|
302 if (rValue > LONG_MAX || rValue < LONG_MIN)
|
Chris@26
|
303 {
|
Chris@26
|
304 setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
|
Chris@26
|
305 return 0;
|
Chris@26
|
306 }
|
Chris@26
|
307 return (long) rValue;
|
Chris@26
|
308 }
|
Chris@26
|
309
|
Chris@26
|
310 // convert string
|
Chris@26
|
311 if (PyString_Check(pyValue))
|
Chris@26
|
312 {
|
Chris@26
|
313 PyObject* pyLong = PyNumber_Long(pyValue);
|
Chris@26
|
314 if (!pyLong)
|
Chris@26
|
315 {
|
Chris@26
|
316 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
317 setValueError("String object can not be converted to long.",m_strict);
|
Chris@26
|
318 return 0;
|
Chris@26
|
319 }
|
Chris@26
|
320 long rValue = this->PyValue_To_Long(pyLong);
|
Chris@26
|
321 if (!m_error) {
|
Chris@26
|
322 Py_DECREF(pyLong);
|
Chris@26
|
323 return rValue;
|
Chris@26
|
324 } else {
|
Chris@26
|
325 Py_CLEAR(pyLong);
|
Chris@26
|
326 setValueError ("Error converting string to long.",m_strict);
|
Chris@26
|
327 return 0;
|
Chris@26
|
328 }
|
Chris@26
|
329 }
|
Chris@26
|
330
|
Chris@26
|
331 // convert the first element of iterable sequences
|
Chris@26
|
332 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
Chris@26
|
333 {
|
Chris@26
|
334 PyObject* item = PySequence_GetItem(pyValue,0);
|
Chris@26
|
335 if (item)
|
Chris@26
|
336 {
|
Chris@26
|
337 size_t rValue = this->PyValue_To_Long(item);
|
Chris@26
|
338 if (!m_error) {
|
Chris@26
|
339 Py_DECREF(item);
|
Chris@26
|
340 return rValue;
|
Chris@26
|
341 } else {
|
Chris@26
|
342 Py_CLEAR(item);
|
Chris@26
|
343 setValueError("Could not convert sequence element to long. ",m_strict);
|
Chris@26
|
344 return 0;
|
Chris@26
|
345 }
|
Chris@26
|
346 }
|
Chris@26
|
347 }
|
Chris@26
|
348
|
Chris@26
|
349 // give up
|
Chris@26
|
350 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
351 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to long is not possible.";
|
Chris@26
|
352 setValueError(msg,m_strict);
|
Chris@26
|
353 #ifdef _DEBUG
|
Chris@26
|
354 cerr << "PyTypeConversions::PyValue_To_Long failed. " << msg << endl;
|
Chris@26
|
355 #endif
|
Chris@26
|
356 return 0;
|
Chris@26
|
357 }
|
Chris@26
|
358
|
Chris@26
|
359
|
Chris@26
|
360 bool
|
Chris@26
|
361 PyTypeConversions::PyValue_To_Bool(PyObject* pyValue) const
|
Chris@26
|
362 {
|
Chris@26
|
363 // convert objects supporting the number protocol
|
Chris@26
|
364 // Note: PyBool is a subclass of PyInt
|
Chris@26
|
365 if (PyNumber_Check(pyValue))
|
Chris@26
|
366 {
|
Chris@26
|
367 if (m_strict && !PyBool_Check(pyValue))
|
Chris@26
|
368 setValueError
|
Chris@26
|
369 ("Strict conversion error: object is not boolean type.",m_strict);
|
Chris@26
|
370
|
Chris@26
|
371 // Note: this function handles Bool,Int,Long,Float
|
Chris@26
|
372 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
Chris@26
|
373 if (PyErr_Occurred())
|
Chris@26
|
374 {
|
Chris@26
|
375 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
376 setValueError ("Error while converting boolean object.",m_strict);
|
Chris@26
|
377 }
|
Chris@26
|
378 if (rValue != 1 && rValue != 0)
|
Chris@26
|
379 {
|
Chris@26
|
380 setValueError ("Overflow error. Object can not be converted to boolean.",m_strict);
|
Chris@26
|
381 }
|
Chris@26
|
382 return (bool) rValue;
|
Chris@26
|
383 }
|
Chris@26
|
384
|
Chris@26
|
385 if (m_strict) {
|
Chris@26
|
386 setValueError ("Strict conversion error: object is not numerical type.",m_strict);
|
Chris@26
|
387 return false;
|
Chris@26
|
388 }
|
Chris@26
|
389
|
Chris@26
|
390 // convert iterables: the rule is the same as in the interpreter:
|
Chris@26
|
391 // empty sequence evaluates to False, anything else is True
|
Chris@26
|
392 if (PySequence_Check(pyValue))
|
Chris@26
|
393 {
|
Chris@26
|
394 return PySequence_Size(pyValue)?true:false;
|
Chris@26
|
395 }
|
Chris@26
|
396
|
Chris@26
|
397 // give up
|
Chris@26
|
398 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
Chris@26
|
399 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to boolean is not possible.";
|
Chris@26
|
400 setValueError(msg,m_strict);
|
Chris@26
|
401 #ifdef _DEBUG
|
Chris@26
|
402 cerr << "PyTypeConversions::PyValue_To_Bool failed. " << msg << endl;
|
Chris@26
|
403 #endif
|
Chris@26
|
404 return false;
|
Chris@26
|
405 }
|
Chris@26
|
406
|
Chris@26
|
407 /// string and objects that support .__str__()
|
Chris@26
|
408 /// TODO: check unicode objects
|
Chris@26
|
409 std::string
|
Chris@26
|
410 PyTypeConversions::PyValue_To_String(PyObject* pyValue) const
|
Chris@26
|
411 {
|
Chris@26
|
412 // convert string
|
Chris@26
|
413 if (PyString_Check(pyValue))
|
Chris@26
|
414 {
|
Chris@26
|
415 char *cstr = PyString_AS_STRING(pyValue);
|
Chris@26
|
416 if (!cstr)
|
Chris@26
|
417 {
|
Chris@26
|
418 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
419 setValueError("Error while converting string object.",m_strict);
|
Chris@26
|
420 return std::string();
|
Chris@26
|
421 }
|
Chris@26
|
422 return std::string(cstr);
|
Chris@26
|
423 }
|
Chris@26
|
424 // TODO: deal with unicode here (argh!)
|
Chris@26
|
425
|
Chris@26
|
426 // in strict mode we will not try harder
|
Chris@26
|
427 if (m_strict) {
|
Chris@26
|
428 setValueError("Strict conversion error: object is not string.",m_strict);
|
Chris@26
|
429 return std::string();
|
Chris@26
|
430 }
|
Chris@26
|
431
|
Chris@26
|
432 // accept None as empty string
|
Chris@26
|
433 if (pyValue == Py_None) return std::string();
|
Chris@26
|
434
|
Chris@26
|
435 // convert list or tuple: empties are turned into empty strings conventionally
|
Chris@26
|
436 if (PyList_Check(pyValue) || PyTuple_Check(pyValue))
|
Chris@26
|
437 {
|
Chris@26
|
438 if (!PySequence_Size(pyValue)) return std::string();
|
Chris@26
|
439 PyObject* item = PySequence_GetItem(pyValue,0);
|
Chris@26
|
440 if (item)
|
Chris@26
|
441 {
|
Chris@26
|
442 std::string rValue = this->PyValue_To_String(item);
|
Chris@26
|
443 if (!m_error) {
|
Chris@26
|
444 Py_DECREF(item);
|
Chris@26
|
445 return rValue;
|
Chris@26
|
446 } else {
|
Chris@26
|
447 Py_CLEAR(item);
|
Chris@26
|
448 setValueError("Could not convert sequence element to string.",m_strict);
|
Chris@26
|
449 return std::string();
|
Chris@26
|
450 }
|
Chris@26
|
451 }
|
Chris@26
|
452 }
|
Chris@26
|
453
|
Chris@26
|
454 // convert any other object that has .__str__() or .__repr__()
|
Chris@26
|
455 PyObject* pyString = PyObject_Str(pyValue);
|
Chris@26
|
456 if (pyString && !PyErr_Occurred())
|
Chris@26
|
457 {
|
Chris@26
|
458 std::string rValue = this->PyValue_To_String(pyString);
|
Chris@26
|
459 if (!m_error) {
|
Chris@26
|
460 Py_DECREF(pyString);
|
Chris@26
|
461 return rValue;
|
Chris@26
|
462 } else {
|
Chris@26
|
463 Py_CLEAR(pyString);
|
Chris@26
|
464 std::string msg = "Object " + this->PyValue_Get_TypeName(pyValue) +" can not be represented as string. ";
|
Chris@26
|
465 setValueError (msg,m_strict);
|
Chris@26
|
466 return std::string();
|
Chris@26
|
467 }
|
Chris@26
|
468 }
|
Chris@26
|
469
|
Chris@26
|
470 // give up
|
Chris@26
|
471 PyErr_Print(); PyErr_Clear();
|
Chris@26
|
472 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to string is not possible.";
|
Chris@26
|
473 setValueError(msg,m_strict);
|
Chris@26
|
474 #ifdef _DEBUG
|
Chris@26
|
475 cerr << "PyTypeConversions::PyValue_To_String failed. " << msg << endl;
|
Chris@26
|
476 #endif
|
Chris@26
|
477 return std::string();
|
Chris@26
|
478 }
|
Chris@26
|
479
|
Chris@26
|
480 /* C Values to Py Values */
|
Chris@26
|
481
|
Chris@26
|
482
|
Chris@26
|
483 PyObject*
|
Chris@26
|
484 PyTypeConversions::PyValue_From_CValue(const char* cValue) const
|
Chris@26
|
485 {
|
Chris@26
|
486 // returns new reference
|
Chris@26
|
487 #ifdef _DEBUG
|
Chris@26
|
488 if (!cValue) {
|
Chris@26
|
489 std::string msg = "PyTypeConversions::PyValue_From_CValue: Null pointer encountered while converting from const char* .";
|
Chris@26
|
490 cerr << msg << endl;
|
Chris@26
|
491 setValueError(msg,m_strict);
|
Chris@26
|
492 return NULL;
|
Chris@26
|
493 }
|
Chris@26
|
494 #endif
|
Chris@26
|
495 PyObject *pyValue = PyString_FromString(cValue);
|
Chris@26
|
496 if (!pyValue)
|
Chris@26
|
497 {
|
Chris@26
|
498 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
499 setValueError("Error while converting from char* or string.",m_strict);
|
Chris@26
|
500 #ifdef _DEBUG
|
Chris@26
|
501 cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from const char*" << endl;
|
Chris@26
|
502 #endif
|
Chris@26
|
503 return NULL;
|
Chris@26
|
504 }
|
Chris@26
|
505 return pyValue;
|
Chris@26
|
506 }
|
Chris@26
|
507
|
Chris@26
|
508 PyObject*
|
Chris@26
|
509 PyTypeConversions::PyValue_From_CValue(size_t cValue) const
|
Chris@26
|
510 {
|
Chris@26
|
511 // returns new reference
|
Chris@26
|
512 PyObject *pyValue = PyInt_FromSsize_t((Py_ssize_t)cValue);
|
Chris@26
|
513 if (!pyValue)
|
Chris@26
|
514 {
|
Chris@26
|
515 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
516 setValueError("Error while converting from size_t.",m_strict);
|
Chris@26
|
517 #ifdef _DEBUG
|
Chris@26
|
518 cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from size_t" << endl;
|
Chris@26
|
519 #endif
|
Chris@26
|
520 return NULL;
|
Chris@26
|
521 }
|
Chris@26
|
522 return pyValue;
|
Chris@26
|
523 }
|
Chris@26
|
524
|
Chris@26
|
525 PyObject*
|
Chris@26
|
526 PyTypeConversions::PyValue_From_CValue(double cValue) const
|
Chris@26
|
527 {
|
Chris@26
|
528 // returns new reference
|
Chris@26
|
529 PyObject *pyValue = PyFloat_FromDouble(cValue);
|
Chris@26
|
530 if (!pyValue)
|
Chris@26
|
531 {
|
Chris@26
|
532 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
533 setValueError("Error while converting from float or double.",m_strict);
|
Chris@26
|
534 #ifdef _DEBUG
|
Chris@26
|
535 cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from float or double" << endl;
|
Chris@26
|
536 #endif
|
Chris@26
|
537 return NULL;
|
Chris@26
|
538 }
|
Chris@26
|
539 return pyValue;
|
Chris@26
|
540 }
|
Chris@26
|
541
|
Chris@26
|
542 PyObject*
|
Chris@26
|
543 PyTypeConversions::PyValue_From_CValue(bool cValue) const
|
Chris@26
|
544 {
|
Chris@26
|
545 // returns new reference
|
Chris@26
|
546 PyObject *pyValue = PyBool_FromLong((long)cValue);
|
Chris@26
|
547 if (!pyValue)
|
Chris@26
|
548 {
|
Chris@26
|
549 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
550 setValueError("Error while converting from bool.",m_strict);
|
Chris@26
|
551 #ifdef _DEBUG
|
Chris@26
|
552 cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from bool" << endl;
|
Chris@26
|
553 #endif
|
Chris@26
|
554 return NULL;
|
Chris@26
|
555 }
|
Chris@26
|
556 return pyValue;
|
Chris@26
|
557 }
|
Chris@26
|
558
|
Chris@26
|
559
|
Chris@26
|
560 /* Sequence Types to C++ Types */
|
Chris@26
|
561
|
Chris@26
|
562 //convert Python list to C++ vector of strings
|
Chris@26
|
563 std::vector<std::string>
|
Chris@26
|
564 PyTypeConversions::PyValue_To_StringVector (PyObject *pyList) const
|
Chris@26
|
565 {
|
Chris@26
|
566
|
Chris@26
|
567 std::vector<std::string> Output;
|
Chris@26
|
568 std::string ListElement;
|
Chris@26
|
569 PyObject *pyString = NULL;
|
Chris@26
|
570
|
Chris@26
|
571 if (PyList_Check(pyList)) {
|
Chris@26
|
572
|
Chris@26
|
573 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
Chris@26
|
574 //Get next list item (Borrowed Reference)
|
Chris@26
|
575 pyString = PyList_GET_ITEM(pyList,i);
|
Chris@26
|
576 ListElement = (string) PyString_AsString(PyObject_Str(pyString));
|
Chris@26
|
577 Output.push_back(ListElement);
|
Chris@26
|
578 }
|
Chris@26
|
579 return Output;
|
Chris@26
|
580 }
|
Chris@26
|
581
|
Chris@26
|
582 // #ifdef _DEBUG
|
Chris@26
|
583 // cerr << "PyTypeConversions::PyValue_To_StringVector: Warning: Value is not list of strings." << endl;
|
Chris@26
|
584 // #endif
|
Chris@26
|
585
|
Chris@26
|
586 /// Assume a single value that can be casted as string
|
Chris@26
|
587 /// this allows to write e.g. Feature.label = 5.2 instead of ['5.2']
|
Chris@26
|
588 Output.push_back(PyValue_To_String(pyList));
|
Chris@26
|
589 if (m_error) {
|
Chris@26
|
590 std::string msg = "Value is not list of strings nor can be casted as string. ";
|
Chris@26
|
591 setValueError(msg,m_strict);
|
Chris@26
|
592 #ifdef _DEBUG
|
Chris@26
|
593 cerr << "PyTypeConversions::PyValue_To_StringVector failed. " << msg << endl;
|
Chris@26
|
594 #endif
|
Chris@26
|
595 }
|
Chris@26
|
596 return Output;
|
Chris@26
|
597 }
|
Chris@26
|
598
|
Chris@26
|
599 //convert PyFeature.value (typically a list or numpy array) to C++ vector of floats
|
Chris@26
|
600 std::vector<float>
|
Chris@26
|
601 PyTypeConversions::PyValue_To_FloatVector (PyObject *pyValue) const
|
Chris@26
|
602 {
|
Chris@26
|
603
|
Chris@26
|
604 #ifdef HAVE_NUMPY
|
Chris@26
|
605 if (m_numpyInstalled)
|
Chris@26
|
606 {
|
Chris@26
|
607 // there are four types of values we may receive from a numpy process:
|
Chris@26
|
608 // * a python scalar,
|
Chris@26
|
609 // * an array scalar, (e.g. numpy.float32)
|
Chris@26
|
610 // * an array with nd = 0 (0D array)
|
Chris@26
|
611 // * an array with nd > 0
|
Chris@26
|
612
|
Chris@26
|
613 /// check for scalars
|
Chris@26
|
614 if (PyArray_CheckScalar(pyValue) || PyFloat_Check(pyValue)) {
|
Chris@26
|
615
|
Chris@26
|
616 std::vector<float> Output;
|
Chris@26
|
617
|
Chris@26
|
618 // we rely on the behaviour the scalars are either floats
|
Chris@26
|
619 // or support the number protocol
|
Chris@26
|
620 // TODO: a potential optimisation is to handle them directly
|
Chris@26
|
621 Output.push_back(PyValue_To_Float(pyValue));
|
Chris@26
|
622 return Output;
|
Chris@26
|
623 }
|
Chris@26
|
624
|
Chris@26
|
625 /// numpy array
|
Chris@26
|
626 if (PyArray_CheckExact(pyValue))
|
Chris@26
|
627 return PyArray_To_FloatVector(pyValue);
|
Chris@26
|
628 }
|
Chris@26
|
629 #endif
|
Chris@26
|
630
|
Chris@26
|
631 /// python list of floats (backward compatible)
|
Chris@26
|
632 if (PyList_Check(pyValue)) {
|
Chris@26
|
633 return PyList_To_FloatVector(pyValue);
|
Chris@26
|
634 }
|
Chris@26
|
635
|
Chris@26
|
636 std::vector<float> Output;
|
Chris@26
|
637
|
Chris@26
|
638 /// finally assume a single value supporting the number protocol
|
Chris@26
|
639 /// this allows to write e.g. Feature.values = 5 instead of [5.00]
|
Chris@26
|
640 Output.push_back(PyValue_To_Float(pyValue));
|
Chris@26
|
641 if (m_error) {
|
Chris@26
|
642 std::string msg = "Value is not list or array of floats nor can be casted as float. ";
|
Chris@26
|
643 setValueError(msg,m_strict);
|
Chris@26
|
644 #ifdef _DEBUG
|
Chris@26
|
645 cerr << "PyTypeConversions::PyValue_To_FloatVector failed. " << msg << endl;
|
Chris@26
|
646 #endif
|
Chris@26
|
647 }
|
Chris@26
|
648 return Output;
|
Chris@26
|
649 }
|
Chris@26
|
650
|
Chris@26
|
651 //convert a list of python floats
|
Chris@26
|
652 std::vector<float>
|
Chris@26
|
653 PyTypeConversions::PyList_To_FloatVector (PyObject *inputList) const
|
Chris@26
|
654 {
|
Chris@26
|
655 std::vector<float> Output;
|
Chris@26
|
656
|
Chris@26
|
657 #ifdef _DEBUG
|
Chris@26
|
658 // This is a low level function normally called from
|
Chris@26
|
659 // PyValue_To_FloatVector(). Checking for list is not required.
|
Chris@26
|
660 if (!PyList_Check(inputList)) {
|
Chris@26
|
661 std::string msg = "Value is not list.";
|
Chris@26
|
662 setValueError(msg,true);
|
Chris@26
|
663 cerr << "PyTypeConversions::PyList_To_FloatVector failed. " << msg << endl;
|
Chris@26
|
664 return Output;
|
Chris@26
|
665 }
|
Chris@26
|
666 #endif
|
Chris@26
|
667
|
Chris@26
|
668 float ListElement;
|
Chris@26
|
669 PyObject *pyFloat = NULL;
|
Chris@26
|
670 PyObject **pyObjectArray = PySequence_Fast_ITEMS(inputList);
|
Chris@26
|
671
|
Chris@26
|
672 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
|
Chris@26
|
673
|
Chris@26
|
674 // pyFloat = PyList_GET_ITEM(inputList,i);
|
Chris@26
|
675 pyFloat = pyObjectArray[i];
|
Chris@26
|
676
|
Chris@26
|
677 #ifdef _DEBUG
|
Chris@26
|
678 if (!pyFloat) {
|
Chris@26
|
679 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
680 cerr << "PyTypeConversions::PyList_To_FloatVector: Could not obtain list element: "
|
Chris@26
|
681 << i << " PyList_GetItem returned NULL! Skipping value." << endl;
|
Chris@26
|
682 continue;
|
Chris@26
|
683 }
|
Chris@26
|
684 #endif
|
Chris@26
|
685
|
Chris@26
|
686 // ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
|
Chris@26
|
687 ListElement = PyValue_To_Float(pyFloat);
|
Chris@26
|
688
|
Chris@26
|
689
|
Chris@26
|
690 #ifdef _DEBUG_VALUES
|
Chris@26
|
691 cerr << "value: " << ListElement << endl;
|
Chris@26
|
692 #endif
|
Chris@26
|
693 Output.push_back(ListElement);
|
Chris@26
|
694 }
|
Chris@26
|
695 return Output;
|
Chris@26
|
696 }
|
Chris@26
|
697
|
Chris@26
|
698 // if numpy is not installed this will not be called,
|
Chris@26
|
699 // therefor we do not check again
|
Chris@26
|
700 #ifdef HAVE_NUMPY
|
Chris@26
|
701 std::vector<float>
|
Chris@26
|
702 PyTypeConversions::PyArray_To_FloatVector (PyObject *pyValue) const
|
Chris@26
|
703 {
|
Chris@26
|
704 std::vector<float> Output;
|
Chris@26
|
705
|
Chris@26
|
706 #ifdef _DEBUG
|
Chris@26
|
707 // This is a low level function, normally called from
|
Chris@26
|
708 // PyValue_To_FloatVector(). Checking the array here is not required.
|
Chris@26
|
709 if (!PyArray_Check(pyValue)) {
|
Chris@26
|
710 std::string msg = "Object has no array conversions.";
|
Chris@26
|
711 setValueError(msg,true);
|
Chris@26
|
712 cerr << "PyTypeConversions::PyArray_To_FloatVector failed. " << msg << endl;
|
Chris@26
|
713 return Output;
|
Chris@26
|
714 }
|
Chris@26
|
715 #endif
|
Chris@26
|
716
|
Chris@26
|
717 PyArrayObject* pyArray = (PyArrayObject*) pyValue;
|
Chris@26
|
718 PyArray_Descr* descr = PyArray_DESCR(pyArray);
|
Chris@26
|
719
|
Chris@26
|
720 /// check raw data and descriptor pointers
|
Chris@26
|
721 if (PyArray_DATA(pyArray) == 0 || descr == 0) {
|
Chris@26
|
722 std::string msg = "NumPy array with NULL data or descriptor pointer encountered.";
|
Chris@26
|
723 setValueError(msg,m_strict);
|
Chris@26
|
724 #ifdef _DEBUG
|
Chris@26
|
725 cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << endl;
|
Chris@26
|
726 #endif
|
Chris@26
|
727 return Output;
|
Chris@26
|
728 }
|
Chris@26
|
729
|
Chris@26
|
730 /// check dimensions
|
Chris@26
|
731 if (PyArray_NDIM(pyArray) != 1) {
|
Chris@26
|
732 std::string msg = "NumPy array must be a one dimensional vector.";
|
Chris@26
|
733 setValueError(msg,m_strict);
|
Chris@26
|
734 #ifdef _DEBUG
|
Chris@26
|
735 cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << " Dims: " << (int) PyArray_NDIM(pyArray) << endl;
|
Chris@26
|
736 #endif
|
Chris@26
|
737 return Output;
|
Chris@26
|
738 }
|
Chris@26
|
739
|
Chris@26
|
740 #ifdef _DEBUG_VALUES
|
Chris@26
|
741 cerr << "PyTypeConversions::PyArray_To_FloatVector: Numpy array verified." << endl;
|
Chris@26
|
742 #endif
|
Chris@26
|
743
|
Chris@26
|
744 /// check strides (useful if array is not continuous)
|
Chris@26
|
745 size_t strides = *((size_t*) PyArray_STRIDES(pyArray));
|
Chris@26
|
746
|
Chris@26
|
747 /// convert the array
|
Chris@26
|
748 switch (descr->type_num)
|
Chris@26
|
749 {
|
Chris@26
|
750 case NPY_FLOAT : // dtype='float32'
|
Chris@26
|
751 return PyArray_Convert<float,float>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
|
Chris@26
|
752 case NPY_DOUBLE : // dtype='float64'
|
Chris@26
|
753 return PyArray_Convert<float,double>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
|
Chris@26
|
754 case NPY_INT : // dtype='int'
|
Chris@26
|
755 return PyArray_Convert<float,int>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
|
Chris@26
|
756 case NPY_LONG : // dtype='long'
|
Chris@26
|
757 return PyArray_Convert<float,long>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
|
Chris@26
|
758 default :
|
Chris@26
|
759 std::string msg = "Unsupported value type in NumPy array object.";
|
Chris@26
|
760 setValueError(msg,m_strict);
|
Chris@26
|
761 #ifdef _DEBUG
|
Chris@26
|
762 cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << endl;
|
Chris@26
|
763 #endif
|
Chris@26
|
764 return Output;
|
Chris@26
|
765 }
|
Chris@26
|
766 }
|
Chris@26
|
767
|
Chris@26
|
768 PyObject *
|
Chris@26
|
769 PyTypeConversions::FloatVector_To_PyArray(const vector<float> &v) const
|
Chris@26
|
770 {
|
Chris@26
|
771 npy_intp ndims[1];
|
Chris@26
|
772 ndims[0] = (int)v.size();
|
Chris@26
|
773 PyObject *arr = PyArray_SimpleNew(1, ndims, dtype_float32);
|
Chris@26
|
774 float *data = (float *)PyArray_DATA((PyArrayObject *)arr);
|
Chris@26
|
775 for (int i = 0; i < ndims[0]; ++i) {
|
Chris@26
|
776 data[i] = v[i];
|
Chris@26
|
777 }
|
Chris@26
|
778 return arr;
|
Chris@26
|
779 }
|
Chris@26
|
780 #endif
|
Chris@26
|
781
|
Chris@26
|
782 PyObject *
|
Chris@26
|
783 PyTypeConversions::PyValue_From_StringVector(const std::vector<std::string> &v) const
|
Chris@26
|
784 {
|
Chris@26
|
785 PyObject *pyList = PyList_New(v.size());
|
Chris@26
|
786 for (size_t i = 0; i < v.size(); ++i) {
|
Chris@26
|
787 PyObject *pyStr = PyString_FromString(v[i].c_str());
|
Chris@26
|
788 PyList_SET_ITEM(pyList, i, pyStr);
|
Chris@26
|
789 }
|
Chris@26
|
790 return pyList;
|
Chris@26
|
791 }
|
Chris@26
|
792
|
Chris@26
|
793
|
Chris@26
|
794 /* Error handling */
|
Chris@26
|
795
|
Chris@26
|
796 void
|
Chris@26
|
797 PyTypeConversions::setValueError (std::string message, bool strict) const
|
Chris@26
|
798 {
|
Chris@26
|
799 m_error = true;
|
Chris@26
|
800 m_errorQueue.push(ValueError(message,strict));
|
Chris@26
|
801 }
|
Chris@26
|
802
|
Chris@26
|
803 /// return a reference to the last error or creates a new one.
|
Chris@26
|
804 ValueError&
|
Chris@26
|
805 PyTypeConversions::lastError() const
|
Chris@26
|
806 {
|
Chris@26
|
807 m_error = false;
|
Chris@26
|
808 if (!m_errorQueue.empty()) return m_errorQueue.back();
|
Chris@26
|
809 else {
|
Chris@26
|
810 m_errorQueue.push(ValueError("Type conversion error.",m_strict));
|
Chris@26
|
811 return m_errorQueue.back();
|
Chris@26
|
812 }
|
Chris@26
|
813 }
|
Chris@26
|
814
|
Chris@26
|
815 /// helper function to iterate over the error message queue:
|
Chris@26
|
816 /// pops the oldest item
|
Chris@26
|
817 ValueError
|
Chris@26
|
818 PyTypeConversions::getError() const
|
Chris@26
|
819 {
|
Chris@26
|
820 if (!m_errorQueue.empty()) {
|
Chris@26
|
821 ValueError e = m_errorQueue.front();
|
Chris@26
|
822 m_errorQueue.pop();
|
Chris@26
|
823 if (m_errorQueue.empty()) m_error = false;
|
Chris@26
|
824 return e;
|
Chris@26
|
825 }
|
Chris@26
|
826 else {
|
Chris@26
|
827 m_error = false;
|
Chris@26
|
828 return ValueError();
|
Chris@26
|
829 }
|
Chris@26
|
830 }
|
Chris@26
|
831
|
Chris@26
|
832 /* Utilities */
|
Chris@26
|
833
|
Chris@26
|
834 /// get the type name of an object
|
Chris@26
|
835 std::string
|
Chris@26
|
836 PyTypeConversions::PyValue_Get_TypeName(PyObject* pyValue) const
|
Chris@26
|
837 {
|
Chris@26
|
838 PyObject *pyType = PyObject_Type(pyValue);
|
Chris@26
|
839 if (!pyType)
|
Chris@26
|
840 {
|
Chris@26
|
841 cerr << "Warning: Object type name could not be found." << endl;
|
Chris@26
|
842 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
843 return std::string ("< unknown type >");
|
Chris@26
|
844 }
|
Chris@26
|
845 PyObject *pyString = PyObject_Str(pyType);
|
Chris@26
|
846 if (!pyString)
|
Chris@26
|
847 {
|
Chris@26
|
848 cerr << "Warning: Object type name could not be found." << endl;
|
Chris@26
|
849 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
850 Py_CLEAR(pyType);
|
Chris@26
|
851 return std::string ("< unknown type >");
|
Chris@26
|
852 }
|
Chris@26
|
853 char *cstr = PyString_AS_STRING(pyString);
|
Chris@26
|
854 if (!cstr)
|
Chris@26
|
855 {
|
Chris@26
|
856 cerr << "Warning: Object type name could not be found." << endl;
|
Chris@26
|
857 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
Chris@26
|
858 Py_DECREF(pyType);
|
Chris@26
|
859 Py_CLEAR(pyString);
|
Chris@26
|
860 return std::string("< unknown type >");
|
Chris@26
|
861 }
|
Chris@26
|
862 Py_DECREF(pyType);
|
Chris@26
|
863 Py_DECREF(pyString);
|
Chris@26
|
864 return std::string(cstr);
|
Chris@26
|
865
|
Chris@26
|
866 }
|