changeset 12:d0d91312e5a2

Prepare attempt to build using VamPy structures
author Chris Cannam
date Thu, 20 Nov 2014 13:03:50 +0000
parents d29c25695f5e
children 628c84ed0ef6
files Makefile pyRealTime.cpp pyRealTime.h vampyhost.cpp
diffstat 4 files changed, 28 insertions(+), 580 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Mar 12 18:20:06 2013 +0000
+++ b/Makefile	Thu Nov 20 13:03:50 2014 +0000
@@ -2,26 +2,17 @@
 PY_INCLUDE_PATH	:= /usr/include/python2.7
 NUMPY_INCLUDE_PATH := /usr/lib/python2.7/site-packages/numpy/core/include
 
-CFLAGS		:= -O2 -fPIC -Wall -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
-CXXFLAGS	:= -O2 -fPIC -Wall -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
+CFLAGS		:= -DHAVE_NUMPY -D_VAMP_PLUGIN_IN_HOST_NAMESPACE=1 -O2 -fPIC -Wall -Werror -Ivampy -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
+CXXFLAGS	:= -DHAVE_NUMPY -D_VAMP_PLUGIN_IN_HOST_NAMESPACE=1 -O2 -fPIC -Wall -Werror -Ivampy -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
 
-LDFLAGS		:= -shared -lpython2.7 -lvamp-hostsdk
-#LDFLAGS		:= -dynamiclib -lpython2.5 /usr/lib/libvamp-hostsdk.a
+LDFLAGS		:= -shared -Wl,-Bstatic -lvamp-hostsdk -Wl,-Bdynamic -Wl,-z,defs -lpython2.7 -ldl
 
+OBJECTS	:= vampy/PyRealTime.o vampy/PyFeature.o vampy/PyFeatureSet.o vampy/PyTypeConversions.o vampyhost.o
 
-all: pyRealTime.so vampyhost.so 
+all: vampyhost.so
 
-pyRealTime.a: pyRealTime.o  
-	ar r $@ pyRealTime.o
-
-pyRealTime.so: pyRealTime.o
-	g++ -shared $^ -o $@ $(LDFLAGS) 
-
-vampyhost.so: vampyhost.o pyRealTime.a
+vampyhost.so: $(OBJECTS)
 	g++ -o $@ -shared $^ $(LDFLAGS)
 
-
 clean:	
-	rm *.o
-	rm *.so
-	rm *.a	
+	rm -f vampy/*.o *.o *.so *.a
--- a/pyRealTime.cpp	Tue Mar 12 18:20:06 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,436 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-/*
-
-  This module exposes a Type Object wrapping Vamp::RealTime
-  together with module level functions to create 
-  new pyRealTime objects from frame count, samplerate or sec,nsec tuples.
-
-  A small API is provided for the C/C++ programmer and relevant
-  functions are exposed to Python.
-
-  TODO: implement number protocol (i.e. wrap arithmetic operators) 
-  partly done
-
-*/
-
-#include <Python.h>
-#include <pyRealTime.h>
-#include "vamp-hostsdk/Plugin.h"
-#include <string>
-
-using namespace std;
-using namespace Vamp;
-
-using Vamp::Plugin;
-using Vamp::RealTime;
-
-/* REAL-TIME TYPE OBJECT */
-
-
-/* Documentation for our new module */
-PyDoc_STRVAR(module_doc,
-             "This module is a thin wrapper around Vamp::RealTime.");
-
-
-/* RealTime Object's Methods */ 
-//Note: these are internals, not exposed by the module but the object
-
-/* Returns a Tuple containing sec and nsec values */
-static PyObject *
-RealTime_values(RealTimeObject *self)
-{
-    return Py_BuildValue("(ii)",
-                         self->rt->sec,self->rt->nsec);
-}
-
-/* Returns a Text representation */
-static PyObject *
-RealTime_toText(RealTimeObject *self, PyObject *args)
-{
-    return Py_BuildValue("s",
-                         self->rt->toText().c_str());
-}
-
-/* String representation called by e.g. str(realtime), print realtime*/
-static PyObject *
-RealTime_repr(PyObject *self)
-{
-    return Py_BuildValue("s",
-                         ((RealTimeObject*)self)->rt->toString().c_str());
-}
-
-
-/* Frame representation */
-static PyObject *
-RealTime_toFrame(PyObject *self, PyObject *args)
-{
-    unsigned int samplerate;
-	
-    if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", 
-                           (unsigned int *) &samplerate )) {
-        PyErr_SetString(PyExc_ValueError, 
-                        "Sample Rate Required.");
-        return NULL;
-    }
-	
-    return Py_BuildValue("k", 
-                         RealTime::realTime2Frame( 
-                             *(const RealTime*) ((RealTimeObject*)self)->rt, 
-                             (unsigned int) samplerate));
-}
-
-/* Conversion of realtime to a double precision floating point value */
-/* ...in Python called by e.g. float(realtime) */
-static PyObject *
-RealTime_float(PyObject *s)
-{
-    double drt = ((double) ((RealTimeObject*)s)->rt->sec + 
-                  (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
-    return PyFloat_FromDouble(drt);	
-}
-
-/* test */
-static PyObject *
-RealTime_test(PyObject *self)
-{
-
-    long frame = 100;
-    unsigned int sampleRate = 22050;
-	
-    const RealTime t = RealTime::frame2RealTime(frame,sampleRate);
-    long back = RealTime::realTime2Frame(t,sampleRate);
-    cerr << "Reverse Conversion: " << back << endl;
-
-    return Py_BuildValue("s",
-                         ((RealTimeObject*)self)->rt->toString().c_str());
-}
-
-
-/* Type object's (RealTime) methods table */
-static PyMethodDef RealTime_methods[] = {
-
-    {"toText",	(PyCFunction)RealTime_toText,	METH_NOARGS,
-     PyDoc_STR("toText() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
-
-    {"values",	(PyCFunction)RealTime_values,	METH_NOARGS,
-     PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
-
-    {"toFrame",	(PyCFunction)RealTime_toFrame,	METH_VARARGS,
-     PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
-
-    {"toFloat",	(PyCFunction)RealTime_float,	METH_NOARGS,
-     PyDoc_STR("float() -> Floating point representation.")},
-
-    {"test",	(PyCFunction)RealTime_test,	METH_VARARGS,
-     PyDoc_STR("test() -> .")},
-	
-    {NULL,		NULL}		/* sentinel */
-};
-
-
-
-/* Function to set basic attributes */
-static int
-RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
-{
-
-    if ( !string(name).compare("sec")) { 
-        self->rt->sec= (int) PyInt_AS_LONG(value);
-        return 0;
-    }
-
-    if ( !string(name).compare("nsec")) { 
-        self->rt->nsec= (int) PyInt_AS_LONG(value);
-        return 0;
-    }
-
-    return -1;
-}
-
-/* Function to get basic attributes */
-static PyObject *
-RealTime_getattr(RealTimeObject *self, char *name)
-{
-
-    if ( !string(name).compare("sec") ) { 
-        return PyInt_FromSsize_t(
-            (Py_ssize_t) self->rt->sec); 
-    } 
-
-    if ( !string(name).compare("nsec") ) { 
-        return PyInt_FromSsize_t(
-            (Py_ssize_t) self->rt->nsec); 
-    } 
-
-    return Py_FindMethod(RealTime_methods, 
-                         (PyObject *)self, name);
-}
-
-
-/* DESTRUCTOR: delete type object */
-static void
-RealTimeObject_dealloc(RealTimeObject *self)
-{
-    delete self->rt; 	//delete the C object
-    PyObject_Del(self); //delete the Python object
-}
-
-/*					 Number Protocol 					*/
-
-
-static PyObject *
-RealTime_add(PyObject *s, PyObject *w)
-{
-
-    RealTimeObject *result = 
-        PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (result == NULL) return NULL;
-
-    result->rt = new RealTime(
-	*((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
-    return (PyObject*)result;
-}
-
-static PyObject *
-RealTime_subtract(PyObject *s, PyObject *w)
-{
-
-    RealTimeObject *result = 
-        PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (result == NULL) return NULL;
-
-    result->rt = new RealTime(
-	*((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
-    return (PyObject*)result;
-}
-
-
-static PyNumberMethods realtime_as_number = {
-    RealTime_add,			/*nb_add*/
-    RealTime_subtract,		/*nb_subtract*/
-    0,						/*nb_multiply*/
-    0,				 		/*nb_divide*/
-    0,						/*nb_remainder*/
-    0,      	            /*nb_divmod*/
-    0,                   	/*nb_power*/
-    0,                  	/*nb_neg*/
-    0,                		/*nb_pos*/
-    0,                  	/*(unaryfunc)array_abs,*/
-    0,                    	/*nb_nonzero*/
-    0,                    	/*nb_invert*/
-    0,       				/*nb_lshift*/
-    0,      				/*nb_rshift*/
-    0,      				/*nb_and*/
-    0,      				/*nb_xor*/
-    0,       				/*nb_or*/
-    0,                      /*nb_coerce*/
-    0,						/*nb_int*/
-    0,				        /*nb_long*/
-    (unaryfunc)RealTime_float,             /*nb_float*/
-    0,               		/*nb_oct*/
-    0,               		/*nb_hex*/
-};
-
-/*					 pyRealTime TypeObject 					*/
-
-
-/* Doc:: 10.3 Type Objects */
-/* static */ PyTypeObject RealTime_Type = {
-    /* The ob_type field must be initialized in the module init function
-     * to be portable to Windows without using C++. */
-    PyObject_HEAD_INIT(NULL)
-    0,						/*ob_size*/
-    "pyRealTime.realtime",				/*tp_name*/
-    sizeof(RealTimeObject),	/*tp_basicsize*/
-    sizeof(RealTime),		/*tp_itemsize*/
-    /*	 	methods	 	*/
-    (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
-    0,						/*tp_print*/
-    (getattrfunc)RealTime_getattr, /*tp_getattr*/
-    (setattrfunc)RealTime_setattr, /*tp_setattr*/
-    0,						/*tp_compare*/
-    RealTime_repr,			/*tp_repr*/
-    &realtime_as_number,	/*tp_as_number*/
-    0,						/*tp_as_sequence*/
-    0,						/*tp_as_mapping*/
-    0,						/*tp_hash*/
-    0,//(ternaryfunc)RealTime_new,                      /*tp_call*/
-    0,                      /*tp_str*/
-    0,                      /*tp_getattro*/
-    0,                      /*tp_setattro*/
-    0,                      /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,     /*tp_flags*/
-    0,                      /*tp_doc*/
-    0,                      /*tp_traverse*/
-    0,                      /*tp_clear*/
-    0,                      /*tp_richcompare*/
-    0,                      /*tp_weaklistoffset*/
-    0,                      /*tp_iter*/
-    0,                      /*tp_iternext*/
-    RealTime_methods,       /*tp_methods*/ //TypeObject Methods
-    0,                      /*tp_members*/
-    0,                      /*tp_getset*/
-    0,                      /*tp_base*/
-    0,                      /*tp_dict*/
-    0,                      /*tp_descr_get*/
-    0,                      /*tp_descr_set*/
-    0,                      /*tp_dictoffset*/
-    0,                      /*tp_init*/
-    0,                      /*tp_alloc*/
-    0,                      /*tp_new*/
-    0,			            /*tp_free*/
-    0,                      /*tp_is_gc*/
-};
-
-
-/*		 Remaining Functions Exposed by the MODULE 					*/
-
-
-/* New RealTime object from Frame (with given samplerate) */
-/*static*/ PyObject *
-RealTime_frame2RealTime(PyObject *ignored, PyObject *args)
-{
-
-    long frame;
-    unsigned int sampleRate;
-
-    if (!PyArg_ParseTuple(args, "lI:realtime.fame2RealTime ", 
-                          &frame, 
-                          &sampleRate))
-        return NULL;
-    /*Doc:: 5.5 Parsing arguments and building values*/
-
-    RealTimeObject *self;
-    self = PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (self == NULL)
-        return NULL;
-
-    self->rt = new RealTime(
-	RealTime::frame2RealTime(frame,sampleRate));
-
-    return (PyObject *) self;
-}
-
-/* New RealTime object from sec and nsec */
-/*static*/ PyObject *
-RealTime_new(PyObject *ignored, PyObject *args)
-{
-
-    unsigned int sec = 0;
-    unsigned int nsec = 0;
-    double unary = 0;
-    const char *fmt = NULL;
-
-    /*Doc:: 5.5 Parsing arguments and building values*/
-    if (
-		
-	!PyArg_ParseTuple(args, "|sd:realtime.new ", 
-                          (const char *) &fmt, 
-                          (double *) &unary) 	&&
-
-	!PyArg_ParseTuple(args, "|II:realtime.new ", 
-                          (unsigned int*) &sec, 
-                          (unsigned int*) &nsec) 
-		
-	) { 
-        PyErr_SetString(PyExc_TypeError, 
-                        "RealTime initialised with wrong arguments.");
-        return NULL; }
-
-    PyErr_Clear();
-
-    RealTimeObject *self = 
-	PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (self == NULL) return NULL;
-
-    self->rt = NULL;
-
-    if (sec == 0 && nsec == 0 && fmt == 0) 
-        self->rt = new RealTime();
-    else if (fmt == 0)
-        self->rt = new RealTime(sec,nsec);
-    else { 
-
-        if (!string(fmt).compare("float") ||
-            !string(fmt).compare("seconds"))  
-            self->rt = new RealTime( 
-                RealTime::fromSeconds((double) unary)); 
-
-        if (!string(fmt).compare("milliseconds")) {
-            self->rt = new RealTime( 
-                RealTime::fromSeconds((double) unary / 1000.0)); }
-    }
-
-    if (!self->rt) { 
-        PyErr_SetString(PyExc_TypeError, 
-                        "RealTime initialised with wrong arguments.");
-        return NULL; 
-    }
-
-    return (PyObject *) self;
-}
-
-
-/* pyRealTime Module's methods table */
-static PyMethodDef Module_methods[] = {
-
-    {"frame2RealTime",	(PyCFunction)RealTime_frame2RealTime,	METH_VARARGS,
-     PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
-
-    {"realtime",	RealTime_new,		METH_VARARGS,
-     PyDoc_STR("realtime() -> returns new RealTime object")},
-	
-    {NULL,		NULL}		/* sentinel */
-};
-
-
-/*				 PyRealTime C API functions 					*/
-
-
-
-/*RealTime from PyRealTime*/
-RealTime*
-PyRealTime_AsPointer (PyObject *self) { 
-
-    RealTimeObject *s = (RealTimeObject*) self; 
-
-    if (!PyRealTime_Check(s)) {
-        PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
-        cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
-        return NULL; }
-    return s->rt; };
-
-/*PyRealTime from RealTime*/
-PyObject* 
-PyRealTime_FromRealTime(Vamp::RealTime *rt) {
-
-    RealTimeObject *self =
-	PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (self == NULL) return NULL;
-
-    self->rt = new RealTime(*rt);
-    return (PyObject*) self;
-    //TODO: check if we need to INCREF here
-}
-
-
-/* Module initialization (includes extern "C" {...}) */
-PyMODINIT_FUNC
-initpyRealTime(void)
-{
-    PyObject *m;
-
-    /* Finalize the type object including setting type of the new type
-     * object; doing it here is required for portability to Windows 
-     * without requiring C++. */
-    if (PyType_Ready(&RealTime_Type) < 0)
-        return;
-
-    /* Create the module and add the functions */
-    m = Py_InitModule3("pyRealTime", Module_methods, module_doc);
-    if (m == NULL)
-        return;
-
-//	PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
-
-}
--- a/pyRealTime.h	Tue Mar 12 18:20:06 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-#ifndef _PYREALTIME_H_
-#define _PYREALTIME_H_
-
-#include "vamp-hostsdk/Plugin.h"
-
-/* RealTime Type Object's structure    */
-/* Doc:: 10.2 Common Object Structures */
-typedef struct {
-    PyObject_HEAD
-    /*PyObject	*rt_attrs;*/
-    Vamp::RealTime *rt;
-} RealTimeObject; 
-
-PyAPI_DATA(PyTypeObject) RealTime_Type;
-
-#define PyRealTime_CheckExact(v) ((v)->ob_type == &RealTime_Type)
-#define PyRealTime_Check(v) PyObject_TypeCheck(v, &RealTime_Type)
-
-/* pyRealTime C API functions */
-//	Example from Python's stringobject.h
-// 	PyAPI_FUNC(PyObject *) PyString_FromString(const char *);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* PyRealTime C API functions */
-	
-PyAPI_FUNC(PyObject *) 
-PyRealTime_FromRealTime(Vamp::RealTime *rt);
-
-PyAPI_FUNC(Vamp::RealTime *) 
-PyRealTime_AsPointer(PyObject *self);
-
-/* PyRealTime Module functions */
-
-PyAPI_FUNC(PyObject *)
-RealTime_new(PyObject *ignored, PyObject *args);
-
-PyAPI_FUNC(PyObject *)
-RealTime_frame2RealTime(PyObject *ignored, PyObject *args);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _PYREALTIME_H_ */
--- a/vampyhost.cpp	Tue Mar 12 18:20:06 2013 +0000
+++ b/vampyhost.cpp	Thu Nov 20 13:03:50 2014 +0000
@@ -3,11 +3,16 @@
 //include for python extension module: must be first
 #include <Python.h>
 #include <vampyhost.h>
-#include <pyRealTime.h>
+
+#include <PyRealTime.h>
 
 //!!! NB all our NumPy stuff is currently using the deprecated API --
 //!!! need to work out how to update this
-#include "numpy/arrayobject.h"
+//#include "numpy/arrayobject.h"
+
+#define HAVE_NUMPY 1 // Required
+
+#include "PyTypeConversions.h"
 
 //includes for vamp host
 #include "vamp-hostsdk/Plugin.h"
@@ -412,71 +417,6 @@
     return Py_True;
 }
 
-// These conversion functions are borrowed from PyTypeInterface in VamPy
-
-template<typename RET, typename DTYPE>
-static
-RET *pyArrayConvert(char* raw_data_ptr, long length, size_t strides)
-{
-    RET *rValue = new RET[length];
-
-    /// check if the array is continuous, if not use strides info
-    if (sizeof(DTYPE)!=strides) {
-        char* data = (char*) raw_data_ptr;
-        for (long i = 0; i<length; ++i){
-            rValue[i] = (RET)(*((DTYPE*)data));
-            data += strides;
-        }
-        return rValue;
-    }
-
-    DTYPE* data = (DTYPE*) raw_data_ptr;
-    for (long i = 0; i<length; ++i){
-        rValue[i] = (RET)data[i];
-    }
-
-    return rValue;
-}
-
-static float *
-pyArrayToFloatArray(PyObject *pyValue)
-{
-    if (!PyArray_Check(pyValue)) {
-        cerr << "pyArrayToFloatArray: Failed, object has no array interface" << endl;
-        return 0;
-    }
-
-    PyArrayObject* pyArray = (PyArrayObject*) pyValue;
-    PyArray_Descr* descr = pyArray->descr;
-
-    /// check raw data and descriptor pointers
-    if (pyArray->data == 0 || descr == 0) {
-        cerr << "pyArrayToFloatArray: Failed, NumPy array has NULL data or descriptor" << endl;
-        return 0;
-    }
-
-    /// check dimensions
-    if (pyArray->nd != 1) {
-        cerr << "pyArrayToFloatArray: Failed, NumPy array is multi-dimensional" << endl;
-        return 0;
-    }
-
-    /// check strides (useful if array is not continuous)
-    size_t strides = *((size_t*) pyArray->strides);
-
-    /// convert the array
-    switch (descr->type_num) {
-    case NPY_FLOAT : // dtype='float32'
-        return pyArrayConvert<float,float>(pyArray->data,pyArray->dimensions[0],strides);
-    case NPY_DOUBLE : // dtype='float64'
-        return pyArrayConvert<float,double>(pyArray->data,pyArray->dimensions[0],strides);
-    default:
-        cerr << "pyArrayToFloatArray: Failed: Unsupported value type " << descr->type_num << " in NumPy array object (only float32, float64 supported)" << endl;
-        return 0;
-    }
-}
-
-
 /* RUN PROCESS */
 
 static PyObject *
@@ -514,8 +454,8 @@
 			"Plugin has not been initialised.");
 	return NULL; }
 
-    size_t channels =  pd->channels;
-    size_t blockSize = pd->blockSize;
+    int channels =  pd->channels;
+//    int blockSize = pd->blockSize;
 
     if (!PyList_Check(pyBuffer)) {
 	PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
@@ -530,16 +470,20 @@
 
     float **inbuf = new float *[channels];
 
+    PyTypeConversions typeConv;
+    typeConv.setNumpyInstalled(true);
+    
+    vector<vector<float> > data;
     for (int c = 0; c < channels; ++c) {
         PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
-        inbuf[c] = pyArrayToFloatArray(cbuf);
-        if (!inbuf[c]) {
-            PyErr_SetString(PyExc_TypeError,"NumPy Array required for each channel in process input.");
-            return NULL;
-        }
+        data.push_back(typeConv.PyArray_To_FloatVector(cbuf));
+    }
+    
+    for (int c = 0; c < channels; ++c) {
+        inbuf[c] = &data[c][0];
     }
 
-    RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime);
+    RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
 
     //Call process and store the output
     pd->output = plugin->process(inbuf, timeStamp);
@@ -547,10 +491,6 @@
     /* TODO:  DO SOMETHONG WITH THE FEATURE SET HERE */
 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
 
-
-    for (int c = 0; c < channels; ++c){
-	delete[] inbuf[c];
-    }
     delete[] inbuf;
 
     return NULL; //!!! Need to return actual features!
@@ -673,13 +613,13 @@
      xx_foo_doc},
 
     /* Add RealTime Module Methods */
-
+/*
     {"frame2RealTime",	(PyCFunction)RealTime_frame2RealTime,	METH_VARARGS,
      PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
 
     {"realtime",	(PyCFunction)RealTime_new,		METH_VARARGS,
      PyDoc_STR("realtime() -> returns new RealTime object")},
-
+*/
     {NULL,		NULL}		/* sentinel */
 };