comparison PyTypeConversions.h @ 26:014c48d6f360

Now we know what we want from Vampy source, bring it in here again and lose the subrepo
author Chris Cannam
date Wed, 26 Nov 2014 09:48:35 +0000
parents
children fb6519598734
comparison
equal deleted inserted replaced
25:5379af6bef00 26:014c48d6f360
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 VampyHost
5
6 Use Vamp audio analysis plugins in Python
7
8 Gyorgy Fazekas and Chris Cannam
9 Centre for Digital Music, Queen Mary, University of London
10 Copyright 2008-2014 Queen Mary, University of London
11
12 Permission is hereby granted, free of charge, to any person
13 obtaining a copy of this software and associated documentation
14 files (the "Software"), to deal in the Software without
15 restriction, including without limitation the rights to use, copy,
16 modify, merge, publish, distribute, sublicense, and/or sell copies
17 of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be
21 included in all copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
27 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
28 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
31 Except as contained in this notice, the names of the Centre for
32 Digital Music; Queen Mary, University of London; and the authors
33 shall not be used in advertising or otherwise to promote the sale,
34 use or other dealings in this Software without prior written
35 authorization.
36 */
37
38 /*
39 PyTypeConversions: Type safe conversion utilities between Python
40 types and basic C/C++ types.
41 */
42
43 #ifndef PY_TYPE_CONVERSIONS_H
44 #define PY_TYPE_CONVERSIONS_H
45
46 #include <Python.h>
47
48 #ifdef HAVE_NUMPY
49 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
50 #define NO_IMPORT_ARRAY
51 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
52 #include "numpy/arrayobject.h"
53 #endif
54
55 #include <vector>
56 #include <queue>
57 #include <string>
58 #include <sstream>
59 #include <iostream>
60
61 using std::cerr;
62 using std::endl;
63
64 #ifdef HAVE_NUMPY
65 enum eArrayDataType {
66 dtype_float32 = (int) NPY_FLOAT,
67 dtype_complex64 = (int) NPY_CFLOAT
68 };
69 #endif
70
71 /* C++ mapping of PyNone Type */
72 struct NoneType {};
73
74 // Data
75 class ValueError
76 {
77 public:
78 ValueError() {}
79 ValueError(std::string m, bool s) : message(m),strict(s) {}
80 std::string location;
81 std::string message;
82 bool strict;
83 std::string str() const {
84 return (location.empty()) ? message : message + "\nLocation: " + location;}
85 void print() const { cerr << str() << endl; }
86 template<typename V> ValueError &operator<< (const V& v)
87 {
88 std::ostringstream ss;
89 ss << v;
90 location += ss.str();
91 return *this;
92 }
93 };
94
95 class PyTypeConversions
96 {
97 public:
98 PyTypeConversions();
99 ~PyTypeConversions();
100
101 // Utilities
102 void setStrictTypingFlag(bool b) {m_strict = b;}
103 void setNumpyInstalled(bool b) {m_numpyInstalled = b;}
104 ValueError getError() const;
105 std::string PyValue_Get_TypeName(PyObject*) const;
106
107 // Basic type conversion: Python to C++
108 float PyValue_To_Float(PyObject*) const;
109 size_t PyValue_To_Size_t(PyObject*) const;
110 bool PyValue_To_Bool(PyObject*) const;
111 std::string PyValue_To_String(PyObject*) const;
112 long PyValue_To_Long(PyObject*) const;
113 // int PyValue_To_Int(PyObject* pyValue) const;
114
115 // C++ to Python
116 PyObject *PyValue_From_CValue(const char*) const;
117 PyObject *PyValue_From_CValue(const std::string& x) const { return PyValue_From_CValue(x.c_str()); }
118 PyObject *PyValue_From_CValue(size_t) const;
119 PyObject *PyValue_From_CValue(double) const;
120 PyObject *PyValue_From_CValue(float x) const { return PyValue_From_CValue((double)x); }
121 PyObject *PyValue_From_CValue(bool) const;
122
123 // Sequence types
124 std::vector<std::string> PyValue_To_StringVector (PyObject*) const;
125 std::vector<float> PyValue_To_FloatVector (PyObject*) const;
126 std::vector<float> PyList_To_FloatVector (PyObject*) const;
127
128 PyObject *PyValue_From_StringVector(const std::vector<std::string> &) const;
129
130 // Numpy types
131 #ifdef HAVE_NUMPY
132 std::vector<float> PyArray_To_FloatVector (PyObject *pyValue) const;
133 PyObject *FloatVector_To_PyArray(const std::vector<float> &) const; // Copying the data
134 #endif
135
136 /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
137 template<typename RET, typename DTYPE>
138 std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
139 {
140 std::vector<RET> rValue;
141
142 /// check if the array is continuous, if not use strides info
143 if (sizeof(DTYPE)!=strides) {
144 #ifdef _DEBUG_VALUES
145 cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
146 #endif
147 char* data = (char*) raw_data_ptr;
148 for (long i = 0; i<length; ++i){
149 rValue.push_back((RET)(*((DTYPE*)data)));
150 #ifdef _DEBUG_VALUES
151 cerr << "value: " << (RET)(*((DTYPE*)data)) << endl;
152 #endif
153 data+=strides;
154 }
155 return rValue;
156 }
157
158 DTYPE* data = (DTYPE*) raw_data_ptr;
159 for (long i = 0; i<length; ++i){
160 #ifdef _DEBUG_VALUES
161 cerr << "value: " << (RET)data[i] << endl;
162 #endif
163 rValue.push_back((RET)data[i]);
164 }
165 return rValue;
166 }
167
168 /// this is a special case. numpy.float64 has an array conversions but no array descriptor
169 std::vector<float> PyArray0D_Convert(PyArrayInterface *ai) const
170 {
171 std::vector<float> rValue;
172 if ((ai->typekind) == *"f")
173 rValue.push_back((float)*(double*)(ai->data));
174 else {
175 setValueError("Unsupported NumPy data type.",m_strict);
176 return rValue;
177 }
178 #ifdef _DEBUG_VALUES
179 cerr << "value: " << rValue[0] << endl;
180 #endif
181 return rValue;
182 }
183
184 private:
185 bool m_strict;
186 mutable bool m_error;
187 mutable std::queue<ValueError> m_errorQueue;
188 bool m_numpyInstalled;
189
190 void setValueError(std::string,bool) const;
191 ValueError& lastError() const;
192
193 public:
194 const bool& error;
195
196 };
197
198 #endif