changeset 66:5664fe298af2

Update to Python 2.7 and clean up the build (avoid using deprecated NumPy API, fix compiler warnings)
author Chris Cannam
date Mon, 17 Nov 2014 09:37:59 +0000
parents 0df94e3f0fdb
children 146d14ab15e7
files Makefile.linux Makefile.osol PyExtensionManager.cpp PyExtensionManager.h PyExtensionModule.cpp PyFeature.cpp PyPlugin.cpp PyPlugin.h PyTypeInterface.cpp PyTypeInterface.h README vampy-main.cpp
diffstat 12 files changed, 47 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.linux	Wed Aug 06 16:02:25 2014 +0100
+++ b/Makefile.linux	Mon Nov 17 09:37:59 2014 +0000
@@ -1,5 +1,5 @@
 
-CXXFLAGS	:= -DHAVE_NUMPY -O2 -Wall -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -fPIC
+CXXFLAGS	:= -DHAVE_NUMPY -O2 -Wall -Werror -fno-strict-aliasing -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -fPIC
 LDFLAGS		:= -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -lpython2.7 -lpthread -Wl,--version-script=vamp-plugin.map
 
 default: vampy.so 
--- a/Makefile.osol	Wed Aug 06 16:02:25 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-
-
-CXX	:= CC
-CXXFLAGS	:= -G -DHAVE_NUMPY -O2 -I../vamp-plugin-sdk -I/usr/include/python2.6 -I/usr/lib/python2.6/site-packages/numpy/core/include -KPIC
-LDFLAGS		:= -G -L../vamp-plugin-sdk -Bstatic -lvamp-sdk -Bdynamic -lpython2.6 -lpthread -Qoption ld -Mvamp-plugin.map
-
-default: vampy.so 
-all: vampy.so vampymod.so
-
-PyExtensionModule.a: PyExtensionModule.o PyRealTime.o PyFeature.o PyParameterDescriptor.o PyOutputDescriptor.o PyFeatureSet.o 
-	ar cr $@ $^
-
-# The standard python extension is .so (even on the Mac)
-vampymod.so: PyExtensionModule.o PyRealTime.o PyFeature.o PyParameterDescriptor.o PyOutputDescriptor.o PyFeatureSet.o 
-	$(CXX) $^ -o $@ $(LDFLAGS) 
-
-vampy.so: PyPlugin.o PyPlugScanner.o vampy-main.o Mutex.o PyTypeInterface.o PyExtensionModule.a  PyExtensionManager.o
-	$(CXX) $^ -o $@ $(LDFLAGS) 
-
-# Install plugin
-#
-INSTALL_DIR			:=$(DESTDIR)/usr/local/lib/vamp
-PYEXAMPLE_DIR			:='Example VamPy Plugins'
-PLUGIN_NAME			:=vampy
-PLUGIN_EXT			:=.so
-
-install:
-	mkdir -p $(INSTALL_DIR)
-	rm -f $(INSTALL_DIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-	cp $(PLUGIN_NAME)$(PLUGIN_EXT) $(INSTALL_DIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-
-installplug : install
-cleanplug : clean
-
-clean:	
-	rm -f *.o
-	rm -f *.a
-	rm -f *$(PLUGIN_EXT)
-
--- a/PyExtensionManager.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyExtensionManager.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -22,7 +22,7 @@
 using std::find;
 
 //static
-char* PyExtensionManager::m_exposedNames[] = {
+const char* PyExtensionManager::m_exposedNames[] = {
 		"ParameterDescriptor",
 		"OutputDescriptor",
 		"ParameterList",
@@ -152,7 +152,7 @@
 	
 	int i = 0;
 	while (PyExtensionManager::m_exposedNames[i]) {
-		char* name = PyExtensionManager::m_exposedNames[i];
+		const char* name = PyExtensionManager::m_exposedNames[i];
 		i++;
 		PyObject *key = PyString_FromString(name);
 		if (!key) break;
--- a/PyExtensionManager.h	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyExtensionManager.h	Mon Nov 17 09:37:59 2014 +0000
@@ -65,7 +65,7 @@
 	void deleteModuleName(string plugKey);
 
 private:
-	static char* m_exposedNames[];
+	static const char* m_exposedNames[];
 	
 	vector<string> m_plugModuleNames;
 	PyObject* m_pyGlobalNamespace;
--- a/PyExtensionModule.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyExtensionModule.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -149,7 +149,7 @@
 // PyDoc_STRVAR(vampy_doc,"This module exposes Vamp plugin data type wrappers.");
 
 static int
-setint(PyObject *d, char *name, int value)
+setint(PyObject *d, const char *name, int value)
 {
 	PyObject *v;
 	int err;
@@ -160,7 +160,7 @@
 }
 
 static int
-setdbl(PyObject *d, char *name, double value)
+setdbl(PyObject *d, const char *name, double value)
 {
 	PyObject *v;
 	int err;
@@ -171,7 +171,7 @@
 }
 
 static int
-setstr(PyObject *d, char *name, char *value)
+setstr(PyObject *d, const char *name, const char *value)
 {
 	PyObject *v;
 	int err;
--- a/PyFeature.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyFeature.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -55,12 +55,12 @@
 	if (!kw || !PyDict_Size(kw)) return (PyObject *) self;
 	PyDict_Merge(self->dict,kw,0);
 
-	static char *kwlist[] = {"timestamp", "hasTimestamp", "duration", "hasDuration", 0};
+	static const char *kwlist[] = {"timestamp", "hasTimestamp", "duration", "hasDuration", 0};
 
 	int i = 0;
 	while (kwlist[i]) {
-		char* name = kwlist[i];
-		char* attr = kwlist[++i];
+		const char* name = kwlist[i];
+		const char* attr = kwlist[++i];
 		i++;
 		PyObject *key = PyString_FromString(name);
 		if (!key) break;
--- a/PyPlugin.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyPlugin.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -310,7 +310,7 @@
 }
 
 bool
-PyPlugin::getBooleanFlag(char flagName[], bool defValue = false) const
+PyPlugin::getBooleanFlag(const char flagName[], bool defValue = false) const
 {
 	bool rValue = defValue;
 	if (PyObject_HasAttrString(m_pyInstance,flagName))
@@ -333,7 +333,7 @@
 }
 
 int
-PyPlugin::getBinaryFlags(char flagName[], eVampyFlags defValue = vf_NULL) const
+PyPlugin::getBinaryFlags(const char flagName[], eVampyFlags defValue = vf_NULL) const
 {
 	int rValue = defValue;
 	if (PyObject_HasAttrString(m_pyInstance,flagName))
@@ -429,7 +429,7 @@
 }
 
 void
-PyPlugin::typeErrorHandler(char *method, bool process) const
+PyPlugin::typeErrorHandler(const char *method, bool process) const
 {
 	bool strict = false;
 	while (m_ti.error) { 
--- a/PyPlugin.h	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyPlugin.h	Mon Nov 17 09:37:59 2014 +0000
@@ -129,17 +129,17 @@
 	
 	FeatureSet processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp);
 
-	bool getBooleanFlag(char flagName[],bool) const;
-	int getBinaryFlags(char flagName[], eVampyFlags) const;
-	void typeErrorHandler(char *method, bool process = false) const;
+	bool getBooleanFlag(const char flagName[],bool) const;
+	int getBinaryFlags(const char flagName[], eVampyFlags) const;
+	void typeErrorHandler(const char *method, bool process = false) const;
 
 	/// simple 'void return' call with no args
-	void genericMethodCall(char *method) const
+	void genericMethodCall(const char *method) const
 	{
 		if (m_debugFlag) cerr << DEBUG_NAME << endl;
 		if ( PyObject_HasAttrString(m_pyInstance,method) ) 
 		{
-			PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL);
+		    PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
 			if (!pyValue) {
 				cerr << PLUGIN_ERROR << "Failed to call method." << endl;
 				if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
@@ -149,12 +149,12 @@
 
 	/// 'no arg with default return value' call
 	template<typename RET> 
-	RET &genericMethodCall(char *method, RET &rValue) const
+	RET &genericMethodCall(const char *method, RET &rValue) const
 	{
 		if (m_debugFlag) cerr << DEBUG_NAME << endl;
 		if ( PyObject_HasAttrString(m_pyInstance,method) ) 
 		{
-			PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL);
+		    PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
 			if (!pyValue) {
 				cerr << PLUGIN_ERROR << "Failed to call method." << endl;
 				if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
@@ -177,7 +177,7 @@
 
 	/// unary call
 	template<typename RET,typename A1>
-	RET genericMethodCallArgs(char *method, A1 arg1) const
+	RET genericMethodCallArgs(const char *method, A1 arg1) const
 	{
 		RET rValue = RET();
 		if (m_debugFlag) cerr << DEBUG_NAME << endl;
@@ -243,7 +243,7 @@
 
 	/// binary call
 	template<typename RET,typename A1,typename A2>
-	RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2) const
+	RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2) const
 	{
 		RET rValue = RET();
 		if (m_debugFlag) cerr << DEBUG_NAME << endl;
@@ -315,7 +315,7 @@
 
 	/// trenary call
 	template<typename RET,typename A1,typename A2,typename A3>
-	RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2, A3 arg3) const
+	RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2, A3 arg3) const
 	{
 		RET rValue = RET();
 		if (m_debugFlag) cerr << DEBUG_NAME << endl;
--- a/PyTypeInterface.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyTypeInterface.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
 /*
 
  * Vampy : This plugin is a wrapper around the Vamp plugin API.
@@ -14,6 +15,7 @@
 #ifdef HAVE_NUMPY
 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
 #define NO_IMPORT_ARRAY
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 #include "numpy/arrayobject.h"
 #endif
 
@@ -40,7 +42,7 @@
 static bool isMapInitialised = false;
 
 /*  Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
-	(EXCEPT FOR TEMPORARY PYTHON OBJECTS)!  						 */
+	(EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
 
 PyTypeInterface::PyTypeInterface() : 
 	m_strict(false),
@@ -698,10 +700,10 @@
 #endif
 
 	PyArrayObject* pyArray = (PyArrayObject*) pyValue;
-	PyArray_Descr* descr = pyArray->descr;
+	PyArray_Descr* descr = PyArray_DESCR(pyArray);
 	
 	/// check raw data and descriptor pointers
-	if (pyArray->data == 0 || descr == 0) {
+	if (PyArray_DATA(pyArray) == 0 || descr == 0) {
 		std::string msg = "NumPy array with NULL data or descriptor pointer encountered.";
 		setValueError(msg,m_strict);
 #ifdef _DEBUG
@@ -711,7 +713,7 @@
 	}
 
 	/// check dimensions
-	if (pyArray->nd != 1) {
+	if (PyArray_NDIM(pyArray) != 1) {
 		std::string msg = "NumPy array must be a one dimensional vector.";
 		setValueError(msg,m_strict);
 #ifdef _DEBUG
@@ -725,19 +727,19 @@
 #endif
 	
 	/// check strides (useful if array is not continuous)
-	size_t strides =  *((size_t*) pyArray->strides);
+	size_t strides =  *((size_t*) PyArray_STRIDES(pyArray));
     
 	/// convert the array
 	switch (descr->type_num)
 	{
 		case NPY_FLOAT : // dtype='float32'
-			return PyArray_Convert<float,float>(pyArray->data,pyArray->dimensions[0],strides);
+			return PyArray_Convert<float,float>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
 		case NPY_DOUBLE : // dtype='float64'
-			return PyArray_Convert<float,double>(pyArray->data,pyArray->dimensions[0],strides);
+			return PyArray_Convert<float,double>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
 		case NPY_INT : // dtype='int'
-			return PyArray_Convert<float,int>(pyArray->data,pyArray->dimensions[0],strides);
+			return PyArray_Convert<float,int>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
 		case NPY_LONG : // dtype='long'
-			return PyArray_Convert<float,long>(pyArray->data,pyArray->dimensions[0],strides);
+			return PyArray_Convert<float,long>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
 		default :
 			std::string msg = "Unsupported value type in NumPy array object.";
 			setValueError(msg,m_strict);
--- a/PyTypeInterface.h	Wed Aug 06 16:02:25 2014 +0100
+++ b/PyTypeInterface.h	Mon Nov 17 09:37:59 2014 +0000
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
 /*
 
  * Vampy : This plugin is a wrapper around the Vamp plugin API.
@@ -20,6 +21,7 @@
 #ifdef HAVE_NUMPY
 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
 #define NO_IMPORT_ARRAY
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 #include "numpy/arrayobject.h"
 #endif
 #include "PyExtensionModule.h"
@@ -296,7 +298,7 @@
 
 	/// Convert DTYPE type 1D NumpyArray to std::vector<RET>
 	template<typename RET, typename DTYPE>
-	std::vector<RET> PyArray_Convert(char* raw_data_ptr, long length, size_t strides) const
+	std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
 	{
 		std::vector<RET> rValue;
 		
@@ -577,8 +579,10 @@
 		PyObject *pyChannelArray = 
 			//args: (dimensions, size in each dim, type kind, pointer to continuous array)
 			PyArray_SimpleNewFromData(1, ndims, typenum, (void*) inputBuffers[i]);
-		// make it read-only: set all flags to false except NPY_C_CONTIGUOUS 
-		((PyArrayObject*)pyChannelArray)->flags = NPY_C_CONTIGUOUS;
+		// make it read-only: set all flags to false except NPY_C_CONTIGUOUS
+		//!!! what about NPY_ARRAY_OWNDATA?
+		PyArray_CLEARFLAGS((PyArrayObject *)pyChannelArray, 0xff);
+		PyArray_ENABLEFLAGS((PyArrayObject *)pyChannelArray, NPY_ARRAY_C_CONTIGUOUS);
 		pyChannelListArray[i] = pyChannelArray;
 	}
 	return pyChannelList;
--- a/README	Wed Aug 06 16:02:25 2014 +0100
+++ b/README	Mon Nov 17 09:37:59 2014 +0000
@@ -16,7 +16,7 @@
 
 	Vamp plugins are typically written in C++. Although currently
 	available plugin hosts are valuable tools in audio research,
-    the long and tedious development cycle of plugins does not 
+	the long and tedious development cycle of plugins does not 
 	support quick prototyping of feature extraction algorithms.
 	Learning the extra skills needed for plugin development or using 
 	scientific libraries available for C and C++ is often outside 
@@ -74,7 +74,7 @@
 
 DEPENDENCIES:
 
-	* Vampy requires Python 2.5 or greater. 
+	* Vampy requires Python 2.7.
 	
 	Note that Vampy does not support the new flavour of Python (3.x) 
 	which breaks language compatibility with the 2.x series.
@@ -166,7 +166,7 @@
 
 USING VAMPY:	
 
-	(1) Make sure you have Python 2.5 or greater installed and you
+	(1) Make sure you have Python 2.7 installed and you
 		have a recent Vamp plugin host application. 
 		(e.g. Sonic Visualier)
 
--- a/vampy-main.cpp	Wed Aug 06 16:02:25 2014 +0100
+++ b/vampy-main.cpp	Mon Nov 17 09:37:59 2014 +0000
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
 /*
 
  * Vampy : This plugin is a wrapper around the Vamp plugin API.
@@ -14,7 +15,8 @@
 #ifdef HAVE_NUMPY
 
 // define a unique API pointer 
-#define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API 
+#define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 #include "numpy/arrayobject.h"
 
 // prevent building with very old versions of numpy