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