Chris@66
|
1 /* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
|
fazekasgy@37
|
2 /*
|
fazekasgy@37
|
3
|
fazekasgy@37
|
4 * Vampy : This plugin is a wrapper around the Vamp plugin API.
|
fazekasgy@37
|
5 * It allows for writing Vamp plugins in Python.
|
fazekasgy@37
|
6
|
fazekasgy@37
|
7 * Centre for Digital Music, Queen Mary University of London.
|
fazekasgy@37
|
8 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
|
fazekasgy@37
|
9 * for licence information.)
|
fazekasgy@37
|
10
|
fazekasgy@37
|
11 */
|
fazekasgy@37
|
12
|
fazekasgy@37
|
13 /*
|
Chris@71
|
14 PyTypeConversions: Type safe conversion utilities between Python types
|
Chris@71
|
15 and basic C/C++ types.
|
fazekasgy@37
|
16 */
|
fazekasgy@37
|
17
|
Chris@71
|
18 #ifndef _PY_TYPE_CONVERSIONS_H_
|
Chris@71
|
19 #define _PY_TYPE_CONVERSIONS_H_
|
fazekasgy@37
|
20 #include <Python.h>
|
fazekasgy@37
|
21 #ifdef HAVE_NUMPY
|
fazekasgy@37
|
22 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
|
fazekasgy@37
|
23 #define NO_IMPORT_ARRAY
|
Chris@66
|
24 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
fazekasgy@37
|
25 #include "numpy/arrayobject.h"
|
fazekasgy@37
|
26 #endif
|
Chris@71
|
27
|
fazekasgy@37
|
28 #include <vector>
|
fazekasgy@37
|
29 #include <queue>
|
fazekasgy@37
|
30 #include <string>
|
fazekasgy@37
|
31 #include <sstream>
|
Chris@71
|
32 #include <iostream>
|
fazekasgy@37
|
33
|
fazekasgy@37
|
34 using std::cerr;
|
fazekasgy@37
|
35 using std::endl;
|
fazekasgy@37
|
36
|
fazekasgy@37
|
37 #ifdef HAVE_NUMPY
|
fazekasgy@37
|
38 enum eArrayDataType {
|
fazekasgy@37
|
39 dtype_float32 = (int) NPY_FLOAT,
|
fazekasgy@37
|
40 dtype_complex64 = (int) NPY_CFLOAT
|
fazekasgy@37
|
41 };
|
fazekasgy@37
|
42 #endif
|
fazekasgy@37
|
43
|
fazekasgy@37
|
44 /* C++ mapping of PyNone Type */
|
fazekasgy@37
|
45 struct NoneType {};
|
Chris@71
|
46
|
Chris@71
|
47 // Data
|
Chris@71
|
48 class ValueError
|
fazekasgy@37
|
49 {
|
fazekasgy@37
|
50 public:
|
Chris@71
|
51 ValueError() {}
|
Chris@71
|
52 ValueError(std::string m, bool s) : message(m),strict(s) {}
|
Chris@71
|
53 std::string location;
|
Chris@71
|
54 std::string message;
|
Chris@71
|
55 bool strict;
|
Chris@71
|
56 std::string str() const {
|
Chris@71
|
57 return (location.empty()) ? message : message + "\nLocation: " + location;}
|
Chris@71
|
58 void print() const { cerr << str() << endl; }
|
Chris@71
|
59 template<typename V> ValueError &operator<< (const V& v)
|
fazekasgy@37
|
60 {
|
Chris@71
|
61 std::ostringstream ss;
|
Chris@71
|
62 ss << v;
|
Chris@71
|
63 location += ss.str();
|
Chris@71
|
64 return *this;
|
Chris@71
|
65 }
|
Chris@71
|
66 };
|
Chris@71
|
67
|
Chris@71
|
68 class PyTypeConversions
|
Chris@71
|
69 {
|
Chris@71
|
70 public:
|
Chris@71
|
71 PyTypeConversions();
|
Chris@71
|
72 ~PyTypeConversions();
|
fazekasgy@37
|
73
|
fazekasgy@37
|
74 // Utilities
|
fazekasgy@37
|
75 void setStrictTypingFlag(bool b) {m_strict = b;}
|
fazekasgy@51
|
76 void setNumpyInstalled(bool b) {m_numpyInstalled = b;}
|
fazekasgy@37
|
77 ValueError getError() const;
|
fazekasgy@37
|
78 std::string PyValue_Get_TypeName(PyObject*) const;
|
fazekasgy@37
|
79
|
fazekasgy@37
|
80 // Basic type conversion: Python to C++
|
fazekasgy@37
|
81 float PyValue_To_Float(PyObject*) const;
|
fazekasgy@37
|
82 size_t PyValue_To_Size_t(PyObject*) const;
|
fazekasgy@37
|
83 bool PyValue_To_Bool(PyObject*) const;
|
fazekasgy@37
|
84 std::string PyValue_To_String(PyObject*) const;
|
fazekasgy@37
|
85 long PyValue_To_Long(PyObject*) const;
|
fazekasgy@37
|
86 // int PyValue_To_Int(PyObject* pyValue) const;
|
fazekasgy@37
|
87
|
fazekasgy@37
|
88 // C++ to Python
|
fazekasgy@37
|
89 PyObject *PyValue_From_CValue(const char*) const;
|
fazekasgy@37
|
90 PyObject *PyValue_From_CValue(const std::string& x) const { return PyValue_From_CValue(x.c_str()); }
|
fazekasgy@37
|
91 PyObject *PyValue_From_CValue(size_t) const;
|
fazekasgy@37
|
92 PyObject *PyValue_From_CValue(double) const;
|
fazekasgy@37
|
93 PyObject *PyValue_From_CValue(float x) const { return PyValue_From_CValue((double)x); }
|
fazekasgy@37
|
94 PyObject *PyValue_From_CValue(bool) const;
|
fazekasgy@37
|
95
|
fazekasgy@37
|
96 // Sequence types
|
fazekasgy@37
|
97 std::vector<std::string> PyValue_To_StringVector (PyObject*) const;
|
fazekasgy@37
|
98 std::vector<float> PyValue_To_FloatVector (PyObject*) const;
|
fazekasgy@37
|
99 std::vector<float> PyList_To_FloatVector (PyObject*) const;
|
fazekasgy@37
|
100
|
fazekasgy@37
|
101 // Numpy types
|
fazekasgy@37
|
102 #ifdef HAVE_NUMPY
|
fazekasgy@37
|
103 std::vector<float> PyArray_To_FloatVector (PyObject *pyValue) const;
|
fazekasgy@37
|
104 #endif
|
fazekasgy@37
|
105
|
fazekasgy@37
|
106 /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
|
fazekasgy@37
|
107 template<typename RET, typename DTYPE>
|
Chris@66
|
108 std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
|
fazekasgy@37
|
109 {
|
fazekasgy@37
|
110 std::vector<RET> rValue;
|
fazekasgy@37
|
111
|
fazekasgy@37
|
112 /// check if the array is continuous, if not use strides info
|
fazekasgy@37
|
113 if (sizeof(DTYPE)!=strides) {
|
fazekasgy@37
|
114 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
115 cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
|
fazekasgy@37
|
116 #endif
|
fazekasgy@37
|
117 char* data = (char*) raw_data_ptr;
|
fazekasgy@37
|
118 for (long i = 0; i<length; ++i){
|
fazekasgy@37
|
119 rValue.push_back((RET)(*((DTYPE*)data)));
|
fazekasgy@37
|
120 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
121 cerr << "value: " << (RET)(*((DTYPE*)data)) << endl;
|
fazekasgy@37
|
122 #endif
|
fazekasgy@37
|
123 data+=strides;
|
fazekasgy@37
|
124 }
|
fazekasgy@37
|
125 return rValue;
|
fazekasgy@37
|
126 }
|
fazekasgy@37
|
127
|
fazekasgy@37
|
128 DTYPE* data = (DTYPE*) raw_data_ptr;
|
fazekasgy@37
|
129 for (long i = 0; i<length; ++i){
|
fazekasgy@37
|
130 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
131 cerr << "value: " << (RET)data[i] << endl;
|
fazekasgy@37
|
132 #endif
|
fazekasgy@37
|
133 rValue.push_back((RET)data[i]);
|
fazekasgy@37
|
134 }
|
fazekasgy@37
|
135 return rValue;
|
fazekasgy@37
|
136 }
|
fazekasgy@37
|
137
|
Chris@71
|
138 /// this is a special case. numpy.float64 has an array conversions but no array descriptor
|
fazekasgy@37
|
139 inline std::vector<float> PyArray0D_Convert(PyArrayInterface *ai) const
|
fazekasgy@37
|
140 {
|
fazekasgy@37
|
141 std::vector<float> rValue;
|
fazekasgy@37
|
142 if ((ai->typekind) == *"f")
|
fazekasgy@37
|
143 rValue.push_back((float)*(double*)(ai->data));
|
fazekasgy@37
|
144 else {
|
fazekasgy@37
|
145 setValueError("Unsupported NumPy data type.",m_strict);
|
fazekasgy@37
|
146 return rValue;
|
fazekasgy@37
|
147 }
|
fazekasgy@37
|
148 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
149 cerr << "value: " << rValue[0] << endl;
|
fazekasgy@37
|
150 #endif
|
fazekasgy@37
|
151 return rValue;
|
fazekasgy@37
|
152 }
|
fazekasgy@37
|
153
|
fazekasgy@37
|
154 private:
|
fazekasgy@37
|
155 bool m_strict;
|
fazekasgy@37
|
156 mutable bool m_error;
|
fazekasgy@37
|
157 mutable std::queue<ValueError> m_errorQueue;
|
fazekasgy@51
|
158 bool m_numpyInstalled;
|
fazekasgy@37
|
159
|
fazekasgy@37
|
160 void setValueError(std::string,bool) const;
|
fazekasgy@37
|
161 ValueError& lastError() const;
|
fazekasgy@37
|
162
|
fazekasgy@37
|
163 public:
|
fazekasgy@37
|
164 const bool& error;
|
fazekasgy@37
|
165
|
fazekasgy@37
|
166 };
|
fazekasgy@37
|
167
|
fazekasgy@37
|
168 #endif
|