comparison PyTypeInterface.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 5664fe298af2
children ffaa1fb3d7de
comparison
equal deleted inserted replaced
70:6c755f3e1173 71:40a01bb24209
10 10
11 */ 11 */
12 12
13 /* 13 /*
14 PyTypeInterface: Type safe conversion utilities between Python types 14 PyTypeInterface: Type safe conversion utilities between Python types
15 and basic C/C++ types and Vamp API types. 15 and Vamp API types. See PyTypeConversions for basic C/C++ types.
16 */ 16 */
17 17
18 #ifndef _PY_TYPE_INTERFACE_H_ 18 #ifndef _PY_TYPE_INTERFACE_H_
19 #define _PY_TYPE_INTERFACE_H_ 19 #define _PY_TYPE_INTERFACE_H_
20 #include <Python.h> 20 #include <Python.h>
23 #define NO_IMPORT_ARRAY 23 #define NO_IMPORT_ARRAY
24 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 24 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
25 #include "numpy/arrayobject.h" 25 #include "numpy/arrayobject.h"
26 #endif 26 #endif
27 #include "PyExtensionModule.h" 27 #include "PyExtensionModule.h"
28 #include "PyTypeConversions.h"
28 #include <vector> 29 #include <vector>
29 #include <queue> 30 #include <queue>
30 #include <string> 31 #include <string>
31 #include <sstream> 32 #include <sstream>
32 #include "vamp-sdk/Plugin.h" 33 #include "vamp-sdk/Plugin.h"
33 34
34 using std::cerr; 35 using std::cerr;
35 using std::endl; 36 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 37
44 namespace o { 38 namespace o {
45 enum eOutDescriptors { 39 enum eOutDescriptors {
46 not_found, 40 not_found,
47 identifier, 41 identifier,
93 duration, 87 duration,
94 values, 88 values,
95 label 89 label
96 }; 90 };
97 91
98 /* C++ mapping of PyNone Type */
99 struct NoneType {};
100
101 class PyTypeInterface 92 class PyTypeInterface
102 { 93 {
94 PyTypeConversions m_conv;
95
103 public: 96 public:
104 PyTypeInterface(); 97 PyTypeInterface();
105 ~PyTypeInterface(); 98 ~PyTypeInterface();
106 99
107 // Data
108 class ValueError
109 {
110 public:
111 ValueError() {}
112 ValueError(std::string m, bool s) : message(m),strict(s) {}
113 std::string location;
114 std::string message;
115 bool strict;
116 std::string str() const {
117 return (location.empty()) ? message : message + "\nLocation: " + location;}
118 void print() const { cerr << str() << endl; }
119 template<typename V> ValueError &operator<< (const V& v)
120 {
121 std::ostringstream ss;
122 ss << v;
123 location += ss.str();
124 return *this;
125 }
126 };
127
128 // Utilities 100 // Utilities
129 void setStrictTypingFlag(bool b) {m_strict = b;} 101 void setStrictTypingFlag(bool b) {m_strict = b; m_conv.setStrictTypingFlag(b);}
130 void setNumpyInstalled(bool b) {m_numpyInstalled = b;} 102 void setNumpyInstalled(bool b) {m_numpyInstalled = b; m_conv.setNumpyInstalled(b); }
131 ValueError getError() const; 103 ValueError getError() const;
132 std::string PyValue_Get_TypeName(PyObject*) const; 104 std::string PyValue_Get_TypeName(PyObject*) const;
133 bool initMaps() const; 105 bool initMaps() const;
134 106
135 // Basic type conversion: Python to C++
136 float PyValue_To_Float(PyObject*) const;
137 size_t PyValue_To_Size_t(PyObject*) const;
138 bool PyValue_To_Bool(PyObject*) const;
139 std::string PyValue_To_String(PyObject*) const;
140 long PyValue_To_Long(PyObject*) const;
141 // int PyValue_To_Int(PyObject* pyValue) const;
142
143
144 // C++ to Python
145 PyObject *PyValue_From_CValue(const char*) const;
146 PyObject *PyValue_From_CValue(const std::string& x) const { return PyValue_From_CValue(x.c_str()); }
147 PyObject *PyValue_From_CValue(size_t) const;
148 PyObject *PyValue_From_CValue(double) const;
149 PyObject *PyValue_From_CValue(float x) const { return PyValue_From_CValue((double)x); }
150 PyObject *PyValue_From_CValue(bool) const;
151
152 // Sequence types
153 std::vector<std::string> PyValue_To_StringVector (PyObject*) const;
154 std::vector<float> PyValue_To_FloatVector (PyObject*) const;
155 std::vector<float> PyList_To_FloatVector (PyObject*) const;
156
157 // Input buffers to Python 107 // Input buffers to Python
158 PyObject* InputBuffers_As_PythonLists(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype); 108 PyObject* InputBuffers_As_PythonLists(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype);
159 PyObject* InputBuffers_As_SharedMemoryList(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype); 109 PyObject* InputBuffers_As_SharedMemoryList(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype);
160 110
161 // Numpy types 111 // Numpy types
162 #ifdef HAVE_NUMPY 112 #ifdef HAVE_NUMPY
163 std::vector<float> PyArray_To_FloatVector (PyObject *pyValue) const;
164 PyObject* InputBuffers_As_NumpyArray(const float *const *inputBuffers, const size_t&, const size_t&, const Vamp::Plugin::InputDomain& dtype); 113 PyObject* InputBuffers_As_NumpyArray(const float *const *inputBuffers, const size_t&, const size_t&, const Vamp::Plugin::InputDomain& dtype);
165 #endif 114 #endif
166 115
167 116 /* Template functions */
168
169
170 /* Template functions */
171 117
172 118
173 /// Common wrappers to set values in Vamp API structs. (to be used in template functions) 119 /// Common wrappers to set values in Vamp API structs. (to be used in template functions)
174 void SetValue(Vamp::Plugin::OutputDescriptor& od, std::string& key, PyObject* pyValue) const; 120 void SetValue(Vamp::Plugin::OutputDescriptor& od, std::string& key, PyObject* pyValue) const;
175 void SetValue(Vamp::Plugin::ParameterDescriptor& od, std::string& key, PyObject* pyValue) const; 121 void SetValue(Vamp::Plugin::ParameterDescriptor& od, std::string& key, PyObject* pyValue) const;
209 RET rd; 155 RET rd;
210 156
211 //Python Dictionary Iterator: 157 //Python Dictionary Iterator:
212 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyDictValue)) 158 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyDictValue))
213 { 159 {
214 std::string key = PyValue_To_String(pyKey); 160 std::string key = m_conv.PyValue_To_String(pyKey);
215 #ifdef _DEBUG_VALUES 161 #ifdef _DEBUG_VALUES
216 cerr << "key: '" << key << "' value: '" << PyValue_To_String(pyDictValue) << "' " << endl; 162 cerr << "key: '" << key << "' value: '" << m_conv.PyValue_To_String(pyDictValue) << "' " << endl;
217 #endif 163 #endif
218 SetValue(rd,key,pyDictValue); 164 SetValue(rd,key,pyDictValue);
219 if (m_error) { 165 if (m_error) {
220 errors++; 166 errors++;
221 lastError() << "attribute '" << key << "'";// << " of " << getDescriptorId(rd); 167 lastError() << "attribute '" << key << "'";// << " of " << getDescriptorId(rd);
294 cerr << "PyTypeInterface::PyValue_To_VampList failed. Expected iterable return type." << endl; 240 cerr << "PyTypeInterface::PyValue_To_VampList failed. Expected iterable return type." << endl;
295 #endif 241 #endif
296 242
297 } 243 }
298 244
299 /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
300 template<typename RET, typename DTYPE>
301 std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
302 {
303 std::vector<RET> rValue;
304
305 /// check if the array is continuous, if not use strides info
306 if (sizeof(DTYPE)!=strides) {
307 #ifdef _DEBUG_VALUES
308 cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
309 #endif
310 char* data = (char*) raw_data_ptr;
311 for (long i = 0; i<length; ++i){
312 rValue.push_back((RET)(*((DTYPE*)data)));
313 #ifdef _DEBUG_VALUES
314 cerr << "value: " << (RET)(*((DTYPE*)data)) << endl;
315 #endif
316 data+=strides;
317 }
318 return rValue;
319 }
320
321 DTYPE* data = (DTYPE*) raw_data_ptr;
322 for (long i = 0; i<length; ++i){
323 #ifdef _DEBUG_VALUES
324 cerr << "value: " << (RET)data[i] << endl;
325 #endif
326 rValue.push_back((RET)data[i]);
327 }
328 return rValue;
329 }
330
331 /// this is a special case. numpy.float64 has an array interface but no array descriptor
332 inline std::vector<float> PyArray0D_Convert(PyArrayInterface *ai) const
333 {
334 std::vector<float> rValue;
335 if ((ai->typekind) == *"f")
336 rValue.push_back((float)*(double*)(ai->data));
337 else {
338 setValueError("Unsupported NumPy data type.",m_strict);
339 return rValue;
340 }
341 #ifdef _DEBUG_VALUES
342 cerr << "value: " << rValue[0] << endl;
343 #endif
344 return rValue;
345 }
346
347 //Vamp specific types 245 //Vamp specific types
348 Vamp::Plugin::FeatureSet PyValue_To_FeatureSet(PyObject*) const; 246 Vamp::Plugin::FeatureSet PyValue_To_FeatureSet(PyObject*) const;
349 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureSet &r) const 247 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureSet &r) const
350 { r = this->PyValue_To_FeatureSet(pyValue); } 248 { r = this->PyValue_To_FeatureSet(pyValue); }
351 249
357 255
358 Vamp::Plugin::InputDomain PyValue_To_InputDomain(PyObject*) const; 256 Vamp::Plugin::InputDomain PyValue_To_InputDomain(PyObject*) const;
359 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::InputDomain &r) const 257 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::InputDomain &r) const
360 { r = this->PyValue_To_InputDomain(pyValue); } 258 { r = this->PyValue_To_InputDomain(pyValue); }
361 259
362
363 /* Overloaded PyValue_To_rValue() to support generic functions */ 260 /* Overloaded PyValue_To_rValue() to support generic functions */
364 inline void PyValue_To_rValue(PyObject *pyValue, float &defValue) const 261 inline void PyValue_To_rValue(PyObject *pyValue, float &defValue) const
365 { float tmp = this->PyValue_To_Float(pyValue); 262 { float tmp = m_conv.PyValue_To_Float(pyValue);
366 if(!m_error) defValue = tmp; } 263 if(!m_error) defValue = tmp; }
367 inline void PyValue_To_rValue(PyObject *pyValue, size_t &defValue) const 264 inline void PyValue_To_rValue(PyObject *pyValue, size_t &defValue) const
368 { size_t tmp = this->PyValue_To_Size_t(pyValue); 265 { size_t tmp = m_conv.PyValue_To_Size_t(pyValue);
369 if(!m_error) defValue = tmp; } 266 if(!m_error) defValue = tmp; }
370 inline void PyValue_To_rValue(PyObject *pyValue, bool &defValue) const 267 inline void PyValue_To_rValue(PyObject *pyValue, bool &defValue) const
371 { bool tmp = this->PyValue_To_Bool(pyValue); 268 { bool tmp = m_conv.PyValue_To_Bool(pyValue);
372 if(!m_error) defValue = tmp; } 269 if(!m_error) defValue = tmp; }
373 inline void PyValue_To_rValue(PyObject *pyValue, std::string &defValue) const 270 inline void PyValue_To_rValue(PyObject *pyValue, std::string &defValue) const
374 { std::string tmp = this->PyValue_To_String(pyValue); 271 { std::string tmp = m_conv.PyValue_To_String(pyValue);
375 if(!m_error) defValue = tmp; } 272 if(!m_error) defValue = tmp; }
376 /*used by templates where we expect no return value, if there is one it will be ignored*/ 273 /*used by templates where we expect no return value, if there is one it will be ignored*/
377 inline void PyValue_To_rValue(PyObject *pyValue, NoneType &defValue) const 274 inline void PyValue_To_rValue(PyObject *pyValue, NoneType &defValue) const
378 { if (m_strict && pyValue != Py_None) 275 { if (m_strict && pyValue != Py_None)
379 setValueError("Strict conversion error: Expected 'None' type.",m_strict); 276 setValueError("Strict conversion error: Expected 'None' type.",m_strict);
380 } 277 }
381 278
382 /* convert sequence types to Vamp List types */ 279 /* convert sequence types to Vamp List types */
383 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::OutputList &r) const 280 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::OutputList &r) const
384 { r = this->PyValue_To_VampList<Vamp::Plugin::OutputList,Vamp::Plugin::OutputDescriptor>(pyValue); } 281 { r = this->PyValue_To_VampList<Vamp::Plugin::OutputList,Vamp::Plugin::OutputDescriptor>(pyValue); }
385 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::ParameterList &r) const 282 inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::ParameterList &r) const
386 { r = this->PyValue_To_VampList<Vamp::Plugin::ParameterList,Vamp::Plugin::ParameterDescriptor>(pyValue); } 283 { r = this->PyValue_To_VampList<Vamp::Plugin::ParameterList,Vamp::Plugin::ParameterDescriptor>(pyValue); }
401 void setValueError(std::string,bool) const; 298 void setValueError(std::string,bool) const;
402 ValueError& lastError() const; 299 ValueError& lastError() const;
403 300
404 /* Overloaded _convert(), bypasses error checking to avoid doing it twice in internals. */ 301 /* Overloaded _convert(), bypasses error checking to avoid doing it twice in internals. */
405 inline void _convert(PyObject *pyValue,float &r) const 302 inline void _convert(PyObject *pyValue,float &r) const
406 { r = PyValue_To_Float(pyValue); } 303 { r = m_conv.PyValue_To_Float(pyValue); }
407 inline void _convert(PyObject *pyValue,size_t &r) const 304 inline void _convert(PyObject *pyValue,size_t &r) const
408 { r = PyValue_To_Size_t(pyValue); } 305 { r = m_conv.PyValue_To_Size_t(pyValue); }
409 inline void _convert(PyObject *pyValue,bool &r) const 306 inline void _convert(PyObject *pyValue,bool &r) const
410 { r = PyValue_To_Bool(pyValue); } 307 { r = m_conv.PyValue_To_Bool(pyValue); }
411 inline void _convert(PyObject *pyValue,std::string &r) const 308 inline void _convert(PyObject *pyValue,std::string &r) const
412 { r = PyValue_To_String(pyValue); } 309 { r = m_conv.PyValue_To_String(pyValue); }
413 inline void _convert(PyObject *pyValue,std::vector<std::string> &r) const 310 inline void _convert(PyObject *pyValue,std::vector<std::string> &r) const
414 { r = PyValue_To_StringVector(pyValue); } 311 { r = m_conv.PyValue_To_StringVector(pyValue); }
415 inline void _convert(PyObject *pyValue,std::vector<float> &r) const 312 inline void _convert(PyObject *pyValue,std::vector<float> &r) const
416 { r = PyValue_To_FloatVector(pyValue); } 313 { r = m_conv.PyValue_To_FloatVector(pyValue); }
417 inline void _convert(PyObject *pyValue,Vamp::RealTime &r) const 314 inline void _convert(PyObject *pyValue,Vamp::RealTime &r) const
418 { r = PyValue_To_RealTime(pyValue); } 315 { r = PyValue_To_RealTime(pyValue); }
419 inline void _convert(PyObject *pyValue,Vamp::Plugin::OutputDescriptor::SampleType &r) const 316 inline void _convert(PyObject *pyValue,Vamp::Plugin::OutputDescriptor::SampleType &r) const
420 { r = PyValue_To_SampleType(pyValue); } 317 { r = PyValue_To_SampleType(pyValue); }
421 // inline void _convert(PyObject *pyValue,Vamp::Plugin::InputDomain &r) const 318 // inline void _convert(PyObject *pyValue,Vamp::Plugin::InputDomain &r) const
422 // { r = PyValue_To_InputDomain(pyValue); } 319 // { r = m_conv.PyValue_To_InputDomain(pyValue); }
423 320
424 321
425 /* Identify descriptors for error reporting */ 322 /* Identify descriptors for error reporting */
426 inline std::string getDescriptorId(Vamp::Plugin::OutputDescriptor d) const 323 inline std::string getDescriptorId(Vamp::Plugin::OutputDescriptor d) const
427 {return std::string("Output Descriptor '") + d.identifier +"' ";} 324 {return std::string("Output Descriptor '") + d.identifier +"' ";}
433 public: 330 public:
434 const bool& error; 331 const bool& error;
435 332
436 }; 333 };
437 334
438 /* Convert Sample Buffers to Python */
439
440 /// passing the sample buffers as builtin python lists
441 /// Optimization: using fast sequence protocol
442 inline PyObject*
443 PyTypeInterface::InputBuffers_As_PythonLists(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype)
444 {
445 //create a list of lists (new references)
446 PyObject *pyChannelList = PyList_New((Py_ssize_t) channels);
447
448 // Pack samples into a Python List Object
449 // pyFloat/pyComplex types will always be new references,
450 // they will be freed when the lists are deallocated.
451
452 PyObject **pyChannelListArray = PySequence_Fast_ITEMS(pyChannelList);
453 for (size_t i=0; i < channels; ++i) {
454
455 size_t arraySize;
456 if (dtype==Vamp::Plugin::FrequencyDomain)
457 arraySize = (blockSize / 2) + 1; //blockSize + 2; if cplx list isn't used
458 else
459 arraySize = blockSize;
460
461 PyObject *pySampleList = PyList_New((Py_ssize_t) arraySize);
462 PyObject **pySampleListArray = PySequence_Fast_ITEMS(pySampleList);
463
464 // Note: passing a complex list crashes the C-style plugin
465 // when it tries to convert it to a numpy array directly.
466 // This plugin will be obsolete, but we have to find a way
467 // to prevent such crash: possibly a numpy bug,
468 // works fine above 1.0.4
469
470 switch (dtype) //(Vamp::Plugin::TimeDomain)
471 {
472 case Vamp::Plugin::TimeDomain :
473
474 for (size_t j = 0; j < arraySize; ++j) {
475 PyObject *pyFloat=PyFloat_FromDouble(
476 (double) inputBuffers[i][j]);
477 pySampleListArray[j] = pyFloat;
478 }
479 break;
480
481 case Vamp::Plugin::FrequencyDomain :
482
483 size_t k = 0;
484 for (size_t j = 0; j < arraySize; ++j) {
485 PyObject *pyComplex=PyComplex_FromDoubles(
486 (double) inputBuffers[i][k],
487 (double) inputBuffers[i][k+1]);
488 pySampleListArray[j] = pyComplex;
489 k += 2;
490 }
491 break;
492
493 }
494 pyChannelListArray[i] = pySampleList;
495 }
496 return pyChannelList;
497 }
498
499 /// numpy buffer interface: passing the sample buffers as shared memory buffers
500 /// Optimization: using sequence protocol for creating the buffer list
501 inline PyObject*
502 PyTypeInterface::InputBuffers_As_SharedMemoryList(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype)
503 {
504 //create a list of buffers (returns new references)
505 PyObject *pyChannelList = PyList_New((Py_ssize_t) channels);
506 PyObject **pyChannelListArray = PySequence_Fast_ITEMS(pyChannelList);
507
508 // Expose memory using the Buffer Interface.
509 // This will pass a pointer which can be recasted in Python code
510 // as complex or float array using Numpy's frombuffer() method
511 // (this will not copy values just keep the starting adresses
512 // for each channel in a list)
513 Py_ssize_t bufferSize;
514
515 if (dtype==Vamp::Plugin::FrequencyDomain)
516 bufferSize = (Py_ssize_t) sizeof(float) * (blockSize+2);
517 else
518 bufferSize = (Py_ssize_t) sizeof(float) * blockSize;
519
520 for (size_t i=0; i < channels; ++i) {
521 PyObject *pyBuffer = PyBuffer_FromMemory
522 ((void *) (float *) inputBuffers[i],bufferSize);
523 pyChannelListArray[i] = pyBuffer;
524 }
525 return pyChannelList;
526 }
527
528
529 /// numpy array interface: passing the sample buffers as 2D numpy array
530 /// Optimization: using array API (needs numpy headers)
531 #ifdef HAVE_NUMPY
532 inline PyObject*
533 PyTypeInterface::InputBuffers_As_NumpyArray(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype)
534 {
535 /*
536 NOTE: We create a list of 1D Numpy arrays for each channel instead
537 of a matrix, because the address space of inputBuffers doesn't seem
538 to be continuous. Although the array strides could be calculated for
539 2 channels (i.e. inputBuffers[1] - inputBuffers[0]) i'm not sure
540 if this can be trusted, especially for more than 2 channels.
541
542 cerr << "First channel: " << inputBuffers[0][0] << " address: " << inputBuffers[0] << endl;
543 if (channels == 2)
544 cerr << "Second channel: " << inputBuffers[1][0] << " address: " << inputBuffers[1] << endl;
545
546 */
547
548 // create a list of arrays (returns new references)
549 PyObject *pyChannelList = PyList_New((Py_ssize_t) channels);
550 PyObject **pyChannelListArray = PySequence_Fast_ITEMS(pyChannelList);
551
552 // Expose memory using the Numpy Array Interface.
553 // This will wrap an array objects around the data.
554 // (will not copy values just steal the starting adresses)
555
556 int arraySize, typenum;
557
558 switch (dtype)
559 {
560 case Vamp::Plugin::TimeDomain :
561 typenum = dtype_float32; //NPY_FLOAT;
562 arraySize = (int) blockSize;
563 break;
564
565 case Vamp::Plugin::FrequencyDomain :
566 typenum = dtype_complex64; //NPY_CFLOAT;
567 arraySize = (int) (blockSize / 2) + 1;
568 break;
569
570 default :
571 cerr << "PyTypeInterface::InputBuffers_As_NumpyArray: Error: Unsupported numpy array data type." << endl;
572 return pyChannelList;
573 }
574
575 // size for each dimension
576 npy_intp ndims[1]={arraySize};
577
578 for (size_t i=0; i < channels; ++i) {
579 PyObject *pyChannelArray =
580 //args: (dimensions, size in each dim, type kind, pointer to continuous array)
581 PyArray_SimpleNewFromData(1, ndims, typenum, (void*) inputBuffers[i]);
582 // make it read-only: set all flags to false except NPY_C_CONTIGUOUS
583 //!!! what about NPY_ARRAY_OWNDATA?
584 PyArray_CLEARFLAGS((PyArrayObject *)pyChannelArray, 0xff);
585 PyArray_ENABLEFLAGS((PyArrayObject *)pyChannelArray, NPY_ARRAY_C_CONTIGUOUS);
586 pyChannelListArray[i] = pyChannelArray;
587 }
588 return pyChannelList;
589 }
590 #endif 335 #endif
591
592
593
594 #ifdef NUMPY_REFERENCE
595 /// This should be all we need to compile without direct dependency,
596 /// but we don't do that. (it may not work on some platforms)
597 typedef struct {
598 int two; /* contains the integer 2 -- simple sanity check */
599 int nd; /* number of dimensions */
600 char typekind; /* kind in array --- character code of typestr */
601 int itemsize; /* size of each element */
602 int flags; /* flags indicating how the data should be interpreted */
603 /* must set ARR_HAS_DESCR bit to validate descr */
604 Py_intptr_t *shape; /* A length-nd array of shape information */
605 Py_intptr_t *strides; /* A length-nd array of stride information */
606 void *data; /* A pointer to the first element of the array */
607 PyObject *descr; /* NULL or data-description (same as descr key */
608 /* of __array_interface__) -- must set ARR_HAS_DESCR */
609 /* flag or this will be ignored. */
610 } PyArrayInterface;
611
612 typedef struct PyArrayObject {
613 PyObject_HEAD
614 char *data; /* pointer to raw data buffer */
615 int nd; /* number of dimensions, also called ndim */
616 npy_intp *dimensions; /* size in each dimension */
617 npy_intp *strides; /* bytes to jump to get to the
618 next element in each dimension */
619 PyObject *base; /* This object should be decref'd
620 upon deletion of array */
621 /* For views it points to the original array */
622 /* For creation from buffer object it points
623 to an object that shold be decref'd on
624 deletion */
625 /* For UPDATEIFCOPY flag this is an array
626 to-be-updated upon deletion of this one */
627 PyArray_Descr *descr; /* Pointer to type structure */
628 int flags; /* Flags describing array -- see below*/
629 PyObject *weakreflist; /* For weakreferences */
630 } PyArrayObject;
631
632 typedef struct _PyArray_Descr {
633 PyObject_HEAD
634 PyTypeObject *typeobj; /* the type object representing an
635 instance of this type -- should not
636 be two type_numbers with the same type
637 object. */
638 char kind; /* kind for this type */
639 char type; /* unique-character representing this type */
640 char byteorder; /* '>' (big), '<' (little), '|'
641 (not-applicable), or '=' (native). */
642 char hasobject; /* non-zero if it has object arrays
643 in fields */
644 int type_num; /* number representing this type */
645 int elsize; /* element size for this type */
646 int alignment; /* alignment needed for this type */
647 struct _arr_descr \
648 *subarray; /* Non-NULL if this type is
649 is an array (C-contiguous)
650 of some other type
651 */
652 PyObject *fields; /* The fields dictionary for this type */
653 /* For statically defined descr this
654 is always Py_None */
655
656 PyObject *names; /* An ordered tuple of field names or NULL
657 if no fields are defined */
658
659 PyArray_ArrFuncs *f; /* a table of functions specific for each
660 basic data descriptor */
661 } PyArray_Descr;
662
663 enum NPY_TYPES { NPY_BOOL=0,
664 NPY_BYTE, NPY_UBYTE,
665 NPY_SHORT, NPY_USHORT,
666 NPY_INT, NPY_UINT,
667 NPY_LONG, NPY_ULONG,
668 NPY_LONGLONG, NPY_ULONGLONG,
669 NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE,
670 NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE,
671 NPY_OBJECT=17,
672 NPY_STRING, NPY_UNICODE,
673 NPY_VOID,
674 NPY_NTYPES,
675 NPY_NOTYPE,
676 NPY_CHAR, /* special flag */
677 NPY_USERDEF=256 /* leave room for characters */
678 };
679 #endif /*NUMPY_REFERENCE*/
680 #endif