annotate PyTypeConversions.h @ 72:ffaa1fb3d7de vampyhost

inline is not a useful keyword with contemporary compilers
author Chris Cannam
date Mon, 24 Nov 2014 09:50:49 +0000
parents 40a01bb24209
children 76355b91cd92
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
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
Chris@72 139 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