comparison PyTypeConversions.cpp @ 71:40a01bb24209 vampyhost

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