annotate PyTypeConversions.h @ 80:049de1137eab vampyhost

Patch from Simon Black for NumPy >1.9 compatibility
author Chris Cannam
date Tue, 15 Mar 2016 16:58:38 +0000
parents e7d03f88ef43
children
rev   line source
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
Chris@73 101 PyObject *PyValue_From_StringVector(const std::vector<std::string> &) const;
Chris@73 102
fazekasgy@37 103 // Numpy types
fazekasgy@37 104 #ifdef HAVE_NUMPY
fazekasgy@37 105 std::vector<float> PyArray_To_FloatVector (PyObject *pyValue) const;
Chris@74 106 PyObject *FloatVector_To_PyArray(const std::vector<float> &) const; // Copying the data
fazekasgy@37 107 #endif
fazekasgy@37 108
fazekasgy@37 109 /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
fazekasgy@37 110 template<typename RET, typename DTYPE>
Chris@66 111 std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
fazekasgy@37 112 {
fazekasgy@37 113 std::vector<RET> rValue;
fazekasgy@37 114
fazekasgy@37 115 /// check if the array is continuous, if not use strides info
fazekasgy@37 116 if (sizeof(DTYPE)!=strides) {
fazekasgy@37 117 #ifdef _DEBUG_VALUES
fazekasgy@37 118 cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
fazekasgy@37 119 #endif
fazekasgy@37 120 char* data = (char*) raw_data_ptr;
fazekasgy@37 121 for (long i = 0; i<length; ++i){
fazekasgy@37 122 rValue.push_back((RET)(*((DTYPE*)data)));
fazekasgy@37 123 #ifdef _DEBUG_VALUES
fazekasgy@37 124 cerr << "value: " << (RET)(*((DTYPE*)data)) << endl;
fazekasgy@37 125 #endif
fazekasgy@37 126 data+=strides;
fazekasgy@37 127 }
fazekasgy@37 128 return rValue;
fazekasgy@37 129 }
fazekasgy@37 130
fazekasgy@37 131 DTYPE* data = (DTYPE*) raw_data_ptr;
fazekasgy@37 132 for (long i = 0; i<length; ++i){
fazekasgy@37 133 #ifdef _DEBUG_VALUES
fazekasgy@37 134 cerr << "value: " << (RET)data[i] << endl;
fazekasgy@37 135 #endif
fazekasgy@37 136 rValue.push_back((RET)data[i]);
fazekasgy@37 137 }
fazekasgy@37 138 return rValue;
fazekasgy@37 139 }
fazekasgy@37 140
Chris@71 141 /// this is a special case. numpy.float64 has an array conversions but no array descriptor
Chris@72 142 std::vector<float> PyArray0D_Convert(PyArrayInterface *ai) const
fazekasgy@37 143 {
fazekasgy@37 144 std::vector<float> rValue;
fazekasgy@37 145 if ((ai->typekind) == *"f")
fazekasgy@37 146 rValue.push_back((float)*(double*)(ai->data));
fazekasgy@37 147 else {
fazekasgy@37 148 setValueError("Unsupported NumPy data type.",m_strict);
fazekasgy@37 149 return rValue;
fazekasgy@37 150 }
fazekasgy@37 151 #ifdef _DEBUG_VALUES
fazekasgy@37 152 cerr << "value: " << rValue[0] << endl;
fazekasgy@37 153 #endif
fazekasgy@37 154 return rValue;
fazekasgy@37 155 }
fazekasgy@37 156
fazekasgy@37 157 private:
fazekasgy@37 158 bool m_strict;
fazekasgy@37 159 mutable bool m_error;
fazekasgy@37 160 mutable std::queue<ValueError> m_errorQueue;
fazekasgy@51 161 bool m_numpyInstalled;
fazekasgy@37 162
fazekasgy@37 163 void setValueError(std::string,bool) const;
fazekasgy@37 164 ValueError& lastError() const;
fazekasgy@37 165
fazekasgy@37 166 public:
fazekasgy@37 167 const bool& error;
fazekasgy@37 168
fazekasgy@37 169 };
fazekasgy@37 170
fazekasgy@37 171 #endif