Chris@66: /* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */ fazekasgy@37: /* fazekasgy@37: fazekasgy@37: * Vampy : This plugin is a wrapper around the Vamp plugin API. fazekasgy@37: * It allows for writing Vamp plugins in Python. fazekasgy@37: fazekasgy@37: * Centre for Digital Music, Queen Mary University of London. fazekasgy@37: * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources fazekasgy@37: * for licence information.) fazekasgy@37: fazekasgy@37: */ fazekasgy@37: fazekasgy@37: /* Chris@71: PyTypeConversions: Type safe conversion utilities between Python types Chris@71: and basic C/C++ types. fazekasgy@37: */ fazekasgy@37: Chris@71: #ifndef _PY_TYPE_CONVERSIONS_H_ Chris@71: #define _PY_TYPE_CONVERSIONS_H_ fazekasgy@37: #include fazekasgy@37: #ifdef HAVE_NUMPY fazekasgy@37: #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API fazekasgy@37: #define NO_IMPORT_ARRAY Chris@66: #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION fazekasgy@37: #include "numpy/arrayobject.h" fazekasgy@37: #endif Chris@71: fazekasgy@37: #include fazekasgy@37: #include fazekasgy@37: #include fazekasgy@37: #include Chris@71: #include fazekasgy@37: fazekasgy@37: using std::cerr; fazekasgy@37: using std::endl; fazekasgy@37: fazekasgy@37: #ifdef HAVE_NUMPY fazekasgy@37: enum eArrayDataType { fazekasgy@37: dtype_float32 = (int) NPY_FLOAT, fazekasgy@37: dtype_complex64 = (int) NPY_CFLOAT fazekasgy@37: }; fazekasgy@37: #endif fazekasgy@37: fazekasgy@37: /* C++ mapping of PyNone Type */ fazekasgy@37: struct NoneType {}; Chris@71: Chris@71: // Data Chris@71: class ValueError fazekasgy@37: { fazekasgy@37: public: Chris@71: ValueError() {} Chris@71: ValueError(std::string m, bool s) : message(m),strict(s) {} Chris@71: std::string location; Chris@71: std::string message; Chris@71: bool strict; Chris@71: std::string str() const { Chris@71: return (location.empty()) ? message : message + "\nLocation: " + location;} Chris@71: void print() const { cerr << str() << endl; } Chris@71: template ValueError &operator<< (const V& v) fazekasgy@37: { Chris@71: std::ostringstream ss; Chris@71: ss << v; Chris@71: location += ss.str(); Chris@71: return *this; Chris@71: } Chris@71: }; Chris@71: Chris@71: class PyTypeConversions Chris@71: { Chris@71: public: Chris@71: PyTypeConversions(); Chris@71: ~PyTypeConversions(); fazekasgy@37: fazekasgy@37: // Utilities fazekasgy@37: void setStrictTypingFlag(bool b) {m_strict = b;} fazekasgy@51: void setNumpyInstalled(bool b) {m_numpyInstalled = b;} fazekasgy@37: ValueError getError() const; fazekasgy@37: std::string PyValue_Get_TypeName(PyObject*) const; fazekasgy@37: fazekasgy@37: // Basic type conversion: Python to C++ fazekasgy@37: float PyValue_To_Float(PyObject*) const; fazekasgy@37: size_t PyValue_To_Size_t(PyObject*) const; fazekasgy@37: bool PyValue_To_Bool(PyObject*) const; fazekasgy@37: std::string PyValue_To_String(PyObject*) const; fazekasgy@37: long PyValue_To_Long(PyObject*) const; fazekasgy@37: // int PyValue_To_Int(PyObject* pyValue) const; fazekasgy@37: fazekasgy@37: // C++ to Python fazekasgy@37: PyObject *PyValue_From_CValue(const char*) const; fazekasgy@37: PyObject *PyValue_From_CValue(const std::string& x) const { return PyValue_From_CValue(x.c_str()); } fazekasgy@37: PyObject *PyValue_From_CValue(size_t) const; fazekasgy@37: PyObject *PyValue_From_CValue(double) const; fazekasgy@37: PyObject *PyValue_From_CValue(float x) const { return PyValue_From_CValue((double)x); } fazekasgy@37: PyObject *PyValue_From_CValue(bool) const; fazekasgy@37: fazekasgy@37: // Sequence types fazekasgy@37: std::vector PyValue_To_StringVector (PyObject*) const; fazekasgy@37: std::vector PyValue_To_FloatVector (PyObject*) const; fazekasgy@37: std::vector PyList_To_FloatVector (PyObject*) const; fazekasgy@37: fazekasgy@37: // Numpy types fazekasgy@37: #ifdef HAVE_NUMPY fazekasgy@37: std::vector PyArray_To_FloatVector (PyObject *pyValue) const; fazekasgy@37: #endif fazekasgy@37: fazekasgy@37: /// Convert DTYPE type 1D NumpyArray to std::vector fazekasgy@37: template Chris@66: std::vector PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const fazekasgy@37: { fazekasgy@37: std::vector rValue; fazekasgy@37: fazekasgy@37: /// check if the array is continuous, if not use strides info fazekasgy@37: if (sizeof(DTYPE)!=strides) { fazekasgy@37: #ifdef _DEBUG_VALUES fazekasgy@37: cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl; fazekasgy@37: #endif fazekasgy@37: char* data = (char*) raw_data_ptr; fazekasgy@37: for (long i = 0; i PyArray0D_Convert(PyArrayInterface *ai) const fazekasgy@37: { fazekasgy@37: std::vector rValue; fazekasgy@37: if ((ai->typekind) == *"f") fazekasgy@37: rValue.push_back((float)*(double*)(ai->data)); fazekasgy@37: else { fazekasgy@37: setValueError("Unsupported NumPy data type.",m_strict); fazekasgy@37: return rValue; fazekasgy@37: } fazekasgy@37: #ifdef _DEBUG_VALUES fazekasgy@37: cerr << "value: " << rValue[0] << endl; fazekasgy@37: #endif fazekasgy@37: return rValue; fazekasgy@37: } fazekasgy@37: fazekasgy@37: private: fazekasgy@37: bool m_strict; fazekasgy@37: mutable bool m_error; fazekasgy@37: mutable std::queue m_errorQueue; fazekasgy@51: bool m_numpyInstalled; fazekasgy@37: fazekasgy@37: void setValueError(std::string,bool) const; fazekasgy@37: ValueError& lastError() const; fazekasgy@37: fazekasgy@37: public: fazekasgy@37: const bool& error; fazekasgy@37: fazekasgy@37: }; fazekasgy@37: fazekasgy@37: #endif