[PD-cvs] externals/grill/py/source bound.cpp, 1.18, 1.19 clmeth.cpp, 1.27, 1.28 modmeth.cpp, 1.23, 1.24 py.cpp, 1.35, 1.36 pyatom.cpp, 1.1, 1.2 pyatom.h, 1.1, 1.2 pybase.cpp, 1.17, 1.18 pybase.h, 1.12, 1.13 pybundle.cpp, 1.1, 1.2 pybundle.h, 1.1, 1.2 pydsp.cpp, 1.6, 1.7 pyext.cpp, 1.46, 1.47 pyext.h, 1.30, 1.31 pymeth.cpp, 1.6, 1.7 pyprefix.h, 1.5, 1.6 pysymbol.cpp, 1.6, 1.7 pysymbol.h, 1.4, 1.5

Thomas Grill xovo at users.sourceforge.net
Wed Mar 7 14:40:16 CET 2007


Update of /cvsroot/pure-data/externals/grill/py/source
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18937/source

Modified Files:
	bound.cpp clmeth.cpp modmeth.cpp py.cpp pyatom.cpp pyatom.h 
	pybase.cpp pybase.h pybundle.cpp pybundle.h pydsp.cpp 
	pyext.cpp pyext.h pymeth.cpp pyprefix.h pysymbol.cpp 
	pysymbol.h 
Log Message:
multiply inlets for py (hot and cold inlets)
small optimizations and fixes
use PyGILState_\*() functionality (enabled with PY_USE_GIL)
updates for DSP processing
__str__ method for pyext, to enable print self calls
added message bundle functionality (pyext.Bundle class)
enable compiled-only scripts (without .py)
enable optimization of Python code in reease build
let _inlets and _outlets default to 0
fix for numpy
some ASSERTs for explicitly created pyext classes (should be runtime checks i guess)
open editor for script under OS X
fixing numpy initialization quirks
enable symbol binding for all callables (not only functions and methods)
_isthreaded is now a data member instead of a method
fix for gcc4
added pyext._list and pyext._tuple to convert input lists to Python sequence objects
enable module packages (module/__init__.py[co]), now also for Max
python-like dotted module.function syntax
cleaned up float vs. int pyext tags
compiler flag to exclude DSP objects
some optimizations and py reload fix
more safety for calls where association python-pd has already been removed
always run Python interpreter in the background


Index: clmeth.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v
retrieving revision 1.27
retrieving revision 1.28
diff -C2 -d -r1.27 -r1.28
*** clmeth.cpp	12 Dec 2005 00:18:42 -0000	1.27
--- clmeth.cpp	7 Mar 2007 13:40:14 -0000	1.28
***************
*** 3,7 ****
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2007 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 44,48 ****
  
  const char *pyext::pyext_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2005 Thomas Grill\n"
  	"\n"
  	"This is the pyext base class. Available methods:\n"
--- 44,48 ----
  
  const char *pyext::pyext_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2007 Thomas Grill\n"
  	"\n"
  	"This is the pyext base class. Available methods:\n"

Index: pyprefix.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyprefix.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** pyprefix.h	1 Aug 2005 11:58:01 -0000	1.5
--- pyprefix.h	7 Mar 2007 13:40:14 -0000	1.6
***************
*** 1,43 ****
! /* 
! 
! py/pyext - python script object for PD and MaxMSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYPREFIX_H
! #define __PYPREFIX_H
! 
! #define FLEXT_ATTRIBUTES 1
! #include <flext.h>
! 
! // hack: must include math.h before Python.h (at least on OSX)
! // otherwise some functions don't get defined
! #include <math.h>
! 
! #if FLEXT_OS == FLEXT_OS_MAC
! #include <Python/Python.h>
! #else
! #include <Python.h>
! #endif
! 
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 501)
! #error You need at least flext version 0.5.1
! #endif
! 
! #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX
! #include <unistd.h>
! #endif
! 
! #if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || PD_MINOR_VERSION < 37)
! #error PD version >= 0.37 required, please upgrade! 
! #endif
! 
! #include <flcontainers.h>
! #include <string>
! 
! 
! #endif
--- 1,43 ----
! /* 
! 
! py/pyext - python script object for PD and MaxMSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYPREFIX_H
! #define __PYPREFIX_H
! 
! #define FLEXT_ATTRIBUTES 1
! #include <flext.h>
! 
! // hack: must include math.h before Python.h (at least on OSX)
! // otherwise some functions don't get defined
! #include <math.h>
! 
! #if FLEXT_OS == FLEXT_OS_MAC
! #include <Python/Python.h>
! #else
! #include <Python.h>
! #endif
! 
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 501)
! #error You need at least flext version 0.5.1
! #endif
! 
! #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX
! #include <unistd.h>
! #endif
! 
! #if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || PD_MINOR_VERSION < 37)
! #error PD version >= 0.37 required, please upgrade! 
! #endif
! 
! #include <flcontainers.h>
! #include <string>
! 
! 
! #endif

Index: pyext.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.h,v
retrieving revision 1.30
retrieving revision 1.31
diff -C2 -d -r1.30 -r1.31
*** pyext.h	12 Dec 2005 00:18:42 -0000	1.30
--- pyext.h	7 Mar 2007 13:40:14 -0000	1.31
***************
*** 115,119 ****
      static bool stcallpy(PyObject *fun,PyObject *args);
  
! 	PyThreadState *pythr;
  
  private:
--- 115,121 ----
      static bool stcallpy(PyObject *fun,PyObject *args);
  
! #ifndef PY_USE_GIL
! 	ThrState pythr;
! #endif
  
  private:

Index: modmeth.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -d -r1.23 -r1.24
*** modmeth.cpp	3 Aug 2006 16:33:37 -0000	1.23
--- modmeth.cpp	7 Mar 2007 13:40:14 -0000	1.24
***************
*** 3,7 ****
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2006 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2007 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 36,40 ****
  
  const char *pybase::py_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2006 Thomas Grill\n"
  	"\n"
  	"This is the pyext module. Available function:\n"
--- 36,40 ----
  
  const char *pybase::py_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2007 Thomas Grill\n"
  	"\n"
  	"This is the pyext module. Available function:\n"

Index: bound.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/bound.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** bound.cpp	21 Sep 2005 10:52:33 -0000	1.18
--- bound.cpp	7 Mar 2007 13:40:14 -0000	1.19
***************
*** 65,69 ****
      pyext *pyth = static_cast<pyext *>(th);
  
! 	PyThreadState *state = pyth->PyLock();
  
  	PyObject *args = MakePyArgs(sym,argc,argv);
--- 65,69 ----
      pyext *pyth = static_cast<pyext *>(th);
  
! 	ThrState state = pyth->PyLock();
  
  	PyObject *args = MakePyArgs(sym,argc,argv);

Index: pyext.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** pyext.cpp	23 Mar 2006 01:42:05 -0000	1.46
--- pyext.cpp	7 Mar 2007 13:40:14 -0000	1.47
***************
*** 118,123 ****
  	pyobj(NULL),
  	inlets(-1),outlets(-1),
!     siginlets(0),sigoutlets(0),
! 	pythr(NULL)
  { 
  #ifdef FLEXT_THREADS
--- 118,125 ----
  	pyobj(NULL),
  	inlets(-1),outlets(-1),
!     siginlets(0),sigoutlets(0)
! #ifndef PY_USE_GIL
! 	,pythr(NULL)
! #endif
  { 
  #ifdef FLEXT_THREADS
***************
*** 142,146 ****
      bool dotted = strrchr(thisName(),'.') != NULL;
  
!     PyThreadState *state = PyLockSys();
  
  	// init script module
--- 144,148 ----
      bool dotted = strrchr(thisName(),'.') != NULL;
  
!     ThrState state = PyLockSys();
  
  	// init script module
***************
*** 195,199 ****
  bool pyext::Init()
  {
! 	PyThreadState *state = PyLockSys();
  
  	if(methname) {
--- 197,201 ----
  bool pyext::Init()
  {
! 	ThrState state = PyLockSys();
  
  	if(methname) {
***************
*** 222,226 ****
      pybase::Exit(); // exit threads
  
! 	PyThreadState *state = PyLockSys();
      DoExit();
  
--- 224,228 ----
      pybase::Exit(); // exit threads
  
! 	ThrState state = PyLockSys();
      DoExit();
  
***************
*** 415,419 ****
  void pyext::m_get(const t_symbol *s)
  {
!     PyThreadState *state = PyLockSys();
  
  	PyObject *pvar  = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */
--- 417,421 ----
  void pyext::m_get(const t_symbol *s)
  {
!     ThrState state = PyLockSys();
  
  	PyObject *pvar  = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */
***************
*** 438,442 ****
  void pyext::m_set(int argc,const t_atom *argv)
  {
!     PyThreadState *state = PyLockSys();
  
      if(argc < 2 || !IsString(argv[0]))
--- 440,444 ----
  void pyext::m_set(int argc,const t_atom *argv)
  {
!     ThrState state = PyLockSys();
  
      if(argc < 2 || !IsString(argv[0]))
***************
*** 543,547 ****
  	bool ret = false;
  
!     PyThreadState *state = PyLock();
  
      // should be enough...
--- 545,549 ----
  	bool ret = false;
  
!     ThrState state = PyLock();
  
      // should be enough...

Index: pyatom.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyatom.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** pyatom.h	8 Jul 2005 14:30:31 -0000	1.1
--- pyatom.h	7 Mar 2007 13:40:14 -0000	1.2
***************
*** 1,19 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "main.h"
! 
! class PyAtom
! {
! public:
!     static size_t Register(PyObject *obj);
!     static PyObject *Retrieve(size_t id);
!     static void Collect();
! };
--- 1,19 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "main.h"
! 
! class PyAtom
! {
! public:
!     static size_t Register(PyObject *obj);
!     static PyObject *Retrieve(size_t id);
!     static void Collect();
! };

Index: pyatom.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyatom.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** pyatom.cpp	8 Jul 2005 14:30:31 -0000	1.1
--- pyatom.cpp	7 Mar 2007 13:40:14 -0000	1.2
***************
*** 1,61 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyatom.h"
! #include <map>
! 
! #define INTV 0.01
! 
! typedef std::map<size_t,PyObject *> ObjMap;
! 
! static ObjMap objmap;
! static size_t collix = 0,curix = 0;
! static double last = 0;
! 
! size_t PyAtom::Register(PyObject *obj)
! {
!     Collect();
! 
!     Py_INCREF(obj);
!     objmap[++curix] = obj;
! 
! #ifdef _DEBUG
! //    post("REG %p (%i)\n",obj,objmap.size());
! #endif
!     return curix;
! }
! 
! PyObject *PyAtom::Retrieve(size_t id)
! {
!     ObjMap::iterator it = objmap.find(id);
!     PyObject *ret = it == objmap.end()?NULL:it->second;
!     Collect();
!     return ret;
! }
! 
! void PyAtom::Collect()
! {
!     for(;;) {
!         ObjMap::iterator it = objmap.begin();
!         if(it == objmap.end() || it->first > collix) break;
!         
!         PyObject *obj = it->second;
!         Py_DECREF(obj);
!         objmap.erase(it);
! 
! #ifdef _DEBUG
! //        post("DEL %p\n",obj);
! #endif
!     }
! 
!     // schedule next collect time
!     double tm = flext::GetTime();
!     if(tm > last+INTV) last = tm,collix = curix;
! }
--- 1,61 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyatom.h"
! #include <map>
! 
! #define INTV 0.01
! 
! typedef std::map<size_t,PyObject *> ObjMap;
! 
! static ObjMap objmap;
! static size_t collix = 0,curix = 0;
! static double last = 0;
! 
! size_t PyAtom::Register(PyObject *obj)
! {
!     Collect();
! 
!     Py_INCREF(obj);
!     objmap[++curix] = obj;
! 
! #ifdef _DEBUG
! //    post("REG %p (%i)\n",obj,objmap.size());
! #endif
!     return curix;
! }
! 
! PyObject *PyAtom::Retrieve(size_t id)
! {
!     ObjMap::iterator it = objmap.find(id);
!     PyObject *ret = it == objmap.end()?NULL:it->second;
!     Collect();
!     return ret;
! }
! 
! void PyAtom::Collect()
! {
!     for(;;) {
!         ObjMap::iterator it = objmap.begin();
!         if(it == objmap.end() || it->first > collix) break;
!         
!         PyObject *obj = it->second;
!         Py_DECREF(obj);
!         objmap.erase(it);
! 
! #ifdef _DEBUG
! //        post("DEL %p\n",obj);
! #endif
!     }
! 
!     // schedule next collect time
!     double tm = flext::GetTime();
!     if(tm > last+INTV) last = tm,collix = curix;
! }

Index: pybundle.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pybundle.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** pybundle.h	12 Dec 2005 13:55:28 -0000	1.1
--- pybundle.h	7 Mar 2007 13:40:14 -0000	1.2
***************
*** 1,15 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYBUNDLE_H
! #define __PYBUNDLE_H
! 
  #include <flext.h>
  
--- 1,15 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYBUNDLE_H
! #define __PYBUNDLE_H
! 
  #include <flext.h>
  
***************
*** 34,60 ****
      #define PY_EXPORT
  #endif
! 
! typedef struct {
!     PyObject_HEAD
!     /* Type-specific fields go here. */
!     flext::MsgBundle *bundle;
! } pyBundle;
! 
! PY_EXPORT extern PyTypeObject pyBundle_Type;
! 
  #define pyBundle_Check(op) PyObject_TypeCheck(op, &pyBundle_Type)
  #define pyBundle_CheckExact(op) ((op)->ob_type == &pyBundle_Type)
  
  
! inline flext::MsgBundle *pyBundle_AS_BUNDLE(PyObject *op) 
! {
!     return ((pyBundle *)op)->bundle;
! }
! 
! inline flext::MsgBundle *pyBundle_AsBundle(PyObject *op) 
! {
!     return pyBundle_Check(op)?pyBundle_AS_BUNDLE(op):NULL;
! }
! 
  
! #endif
--- 34,60 ----
      #define PY_EXPORT
  #endif
! 
! typedef struct {
!     PyObject_HEAD
!     /* Type-specific fields go here. */
!     flext::MsgBundle *bundle;
! } pyBundle;
! 
! PY_EXPORT extern PyTypeObject pyBundle_Type;
! 
  #define pyBundle_Check(op) PyObject_TypeCheck(op, &pyBundle_Type)
  #define pyBundle_CheckExact(op) ((op)->ob_type == &pyBundle_Type)
  
  
! inline flext::MsgBundle *pyBundle_AS_BUNDLE(PyObject *op) 
! {
!     return ((pyBundle *)op)->bundle;
! }
  
! inline flext::MsgBundle *pyBundle_AsBundle(PyObject *op) 
! {
!     return pyBundle_Check(op)?pyBundle_AS_BUNDLE(op):NULL;
! }
! 
! 
! #endif

Index: pysymbol.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** pysymbol.cpp	20 Jan 2007 14:27:22 -0000	1.6
--- pysymbol.cpp	7 Mar 2007 13:40:14 -0000	1.7
***************
*** 1,254 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyprefix.h"
! #include "pysymbol.h"
! 
! inline pySymbol *symbol_newsym(const t_symbol *sym)
! {
!     pySymbol *self = (pySymbol *)pySymbol_Type.tp_alloc(&pySymbol_Type, 0);
!     if(self) self->sym = sym;
!     return self;
! }
! 
! static PyObject *symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
! {
!     return (PyObject *)symbol_newsym(flext::sym__);
! }
! 
! static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
! 
!     PyObject *arg = PySequence_GetItem(args,0); // new reference
!     if(!arg) return -1;
! 
!     int ret = 0;
! 
!     if(pySymbol_Check(arg))
!         ((pySymbol *)self)->sym = pySymbol_AS_SYMBOL(arg);
!     else if(PyString_Check(arg))
!         ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg));
!     else {
!         PyErr_SetString(PyExc_TypeError,"string or symbol argument expected");
!         ret = -1;
!     }
!     Py_DECREF(arg);
! 
!     return ret;
! }
! 
! static PyObject *symbol_str(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (PyObject *)PyString_FromString(pySymbol_AS_STRING(self));
! }
! 
! static PyObject *symbol_repr(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (PyObject *)PyString_FromFormat("<Symbol %s>",pySymbol_AS_STRING(self));
! }
! 
! static PyObject *symbol_richcompare(PyObject *a,PyObject *b,int cmp)
! {
!     if(pySymbol_Check(a) && pySymbol_Check(b)) {
!         const t_symbol *asym = pySymbol_AS_SYMBOL(a);
!         const t_symbol *bsym = pySymbol_AS_SYMBOL(b);
!         bool ret;
!         switch(cmp) {
!             case Py_LT: ret = asym < bsym; break;
!             case Py_LE: ret = asym <= bsym; break;
!             case Py_EQ: ret = asym == bsym; break;
!             case Py_NE: ret = asym != bsym; break;
!             case Py_GT: ret = asym > bsym; break;
!             case Py_GE: ret = asym >= bsym; break;
!         }
!         return PyBool_FromLong(ret);
!     }
! 	Py_INCREF(Py_NotImplemented);
! 	return Py_NotImplemented;
! }
! 
! static long symbol_hash(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (long)pySymbol_AS_SYMBOL(self);
! }
! 
! 
! static int symbol_length(pySymbol *self)
! {
!     return strlen(flext::GetString(self->sym));
! }
! 
! static PyObject *symbol_item(pySymbol *self, int i)
! {
!     const char *str = flext::GetString(self->sym);
!     int len = strlen(str);
!     if(i < 0) i += len;
! 
!     if(i >= 0 && i < len)
!         return PyString_FromStringAndSize(str+i,1);
!     else {
!         Py_INCREF(Py_None);
!         return Py_None;
!     }
! }
! 
! static PyObject *symbol_slice(pySymbol *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2))
! {
!     const char *str = flext::GetString(self->sym);
!     int len = strlen(str);
!     if(ilow < 0) {
!         ilow += len;
!         if(ilow < 0) ilow = 0;
!     }
!     if(ihigh < 0) ihigh += len;
!     if(ihigh >= len) ihigh = len-1;
! 
!     return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0);
! }
! 
! static PyObject *symbol_concat(pySymbol *self,PyObject *op)
! {
!     PyObject *nobj = symbol_slice(self); // take all
!     if(nobj) {
!         PyObject *ret = PySequence_Concat(nobj,op);
!         Py_DECREF(nobj);
!         return ret;
!     }
!     else
!         return NULL;
! }
! 
! static PyObject *symbol_repeat(pySymbol *self,int rep)
! {
!     PyObject *nobj = symbol_slice(self); // take all
!     if(nobj) {
!         PyObject *ret = PySequence_Repeat(nobj,rep);
!         Py_DECREF(nobj);
!         return ret;
!     }
!     else
!         return NULL;
! }
! 
! static PySequenceMethods symbol_as_seq = {
! 	(inquiry)symbol_length,			/* inquiry sq_length;             __len__ */
! 	(binaryfunc)symbol_concat,          /* __add__ */
! 	(intargfunc)symbol_repeat,          /* __mul__ */
! 	(intargfunc)symbol_item,			/* intargfunc sq_item;            __getitem__ */
! 	(intintargfunc)symbol_slice,		 /* intintargfunc sq_slice;        __getslice__ */
! 	NULL,		/* intobjargproc sq_ass_item;     __setitem__ */
! 	NULL,	/* intintobjargproc sq_ass_slice; __setslice__ */
! };
! 
! static PyObject *symbol_iter(PyObject *obj)
! {
!     pySymbol *self = (pySymbol *)obj;
!     PyObject *nobj = symbol_slice(self);
!     if(nobj) {
!         PyObject *it = PyObject_GetIter(nobj);
!         Py_DECREF(nobj);
!         return it;
!     }
!     else
!         return NULL;
! }
! 
! 
! 
! PyTypeObject pySymbol_Type = {
!     PyObject_HEAD_INIT(NULL)
!     0,                         /*ob_size*/
!     "Symbol",              /*tp_name*/
!     sizeof(pySymbol),          /*tp_basicsize*/
!     0,                         /*tp_itemsize*/
!     0,                         /*tp_dealloc*/
!     0,                         /*tp_print*/
!     0,                         /*tp_getattr*/
!     0,                         /*tp_setattr*/
!     0,            /*tp_compare*/
!     symbol_repr,               /*tp_repr*/
!     0,                         /*tp_as_number*/
!     &symbol_as_seq,            /*tp_as_sequence*/
!     0,                         /*tp_as_mapping*/
!     symbol_hash,               /*tp_hash */
!     0,                         /*tp_call*/
!     symbol_str,                /*tp_str*/
!     0,                         /*tp_getattro*/
!     0,                         /*tp_setattro*/
!     0,                         /*tp_as_buffer*/
!     Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/,   /*tp_flags*/
!     "Symbol objects",           /* tp_doc */
!     0,		               /* tp_traverse */
!     0,		               /* tp_clear */
!     symbol_richcompare,	       /* tp_richcompare */
!     0,		               /* tp_weaklistoffset */
!     symbol_iter,		    /* tp_iter */
!     0,		               /* tp_iternext */
!     0,                          /* tp_methods */
!     0,                          /* tp_members */
!     0,                         /* tp_getset */
!     0,                         /* tp_base */
!     0,                         /* tp_dict */
!     0,                         /* tp_descr_get */
!     0,                         /* tp_descr_set */
!     0,                         /* tp_dictoffset */
!     symbol_init,            /* tp_init */
!     0,                         /* tp_alloc */
!     symbol_new,                 /* tp_new */
! };
! 
! pySymbol *pySymbol__;
! pySymbol *pySymbol_bang;
! pySymbol *pySymbol_list;
! pySymbol *pySymbol_symbol;
! pySymbol *pySymbol_float;
! pySymbol *pySymbol_int;
! 
! 
! void initsymbol()
! {
!     if(PyType_Ready(&pySymbol_Type) < 0)
!         return;
! 
! 	Py_INCREF(&pySymbol_Type);
! 
!     // initialize predefined objects
!     pySymbol__ = symbol_newsym(flext::sym__);
!     pySymbol_bang = symbol_newsym(flext::sym_bang);
!     pySymbol_list = symbol_newsym(flext::sym_list);
!     pySymbol_symbol = symbol_newsym(flext::sym_symbol);
!     pySymbol_float = symbol_newsym(flext::sym_float);
!     pySymbol_int = symbol_newsym(flext::sym_int);
! }
! 
! 
! PyObject *pySymbol_FromSymbol(const t_symbol *sym)
! {
!     pySymbol *op;
!     if(sym == flext::sym__)
!         Py_INCREF(op = pySymbol__);
!     else if(sym == flext::sym_bang)
!         Py_INCREF(op = pySymbol_bang);
!     else if(sym == flext::sym_list)
!         Py_INCREF(op = pySymbol_list);
!     else if(sym == flext::sym_symbol)
!         Py_INCREF(op = pySymbol_symbol);
!     else if(sym == flext::sym_float)
!         Py_INCREF(op = pySymbol_float);
!     else if(sym == flext::sym_int)
!         Py_INCREF(op = pySymbol_int);
!     else
!         op = symbol_newsym(sym);
!     return (PyObject *)op;
! }
--- 1,254 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyprefix.h"
! #include "pysymbol.h"
! 
! inline pySymbol *symbol_newsym(const t_symbol *sym)
! {
!     pySymbol *self = (pySymbol *)pySymbol_Type.tp_alloc(&pySymbol_Type, 0);
!     if(self) self->sym = sym;
!     return self;
! }
! 
! static PyObject *symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
! {
!     return (PyObject *)symbol_newsym(flext::sym__);
! }
! 
! static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
! 
!     PyObject *arg = PySequence_GetItem(args,0); // new reference
!     if(!arg) return -1;
! 
!     int ret = 0;
! 
!     if(pySymbol_Check(arg))
!         ((pySymbol *)self)->sym = pySymbol_AS_SYMBOL(arg);
!     else if(PyString_Check(arg))
!         ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg));
!     else {
!         PyErr_SetString(PyExc_TypeError,"string or symbol argument expected");
!         ret = -1;
!     }
!     Py_DECREF(arg);
! 
!     return ret;
! }
! 
! static PyObject *symbol_str(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (PyObject *)PyString_FromString(pySymbol_AS_STRING(self));
! }
! 
! static PyObject *symbol_repr(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (PyObject *)PyString_FromFormat("<Symbol %s>",pySymbol_AS_STRING(self));
! }
! 
! static PyObject *symbol_richcompare(PyObject *a,PyObject *b,int cmp)
! {
!     if(pySymbol_Check(a) && pySymbol_Check(b)) {
!         const t_symbol *asym = pySymbol_AS_SYMBOL(a);
!         const t_symbol *bsym = pySymbol_AS_SYMBOL(b);
!         bool ret;
!         switch(cmp) {
!             case Py_LT: ret = asym < bsym; break;
!             case Py_LE: ret = asym <= bsym; break;
!             case Py_EQ: ret = asym == bsym; break;
!             case Py_NE: ret = asym != bsym; break;
!             case Py_GT: ret = asym > bsym; break;
!             case Py_GE: ret = asym >= bsym; break;
!         }
!         return PyBool_FromLong(ret);
!     }
! 	Py_INCREF(Py_NotImplemented);
! 	return Py_NotImplemented;
! }
! 
! static long symbol_hash(PyObject *self)
! {
!     FLEXT_ASSERT(pySymbol_Check(self));
!     return (long)pySymbol_AS_SYMBOL(self);
! }
! 
! 
! static int symbol_length(pySymbol *self)
! {
!     return strlen(flext::GetString(self->sym));
! }
! 
! static PyObject *symbol_item(pySymbol *self, int i)
! {
!     const char *str = flext::GetString(self->sym);
!     int len = strlen(str);
!     if(i < 0) i += len;
! 
!     if(i >= 0 && i < len)
!         return PyString_FromStringAndSize(str+i,1);
!     else {
!         Py_INCREF(Py_None);
!         return Py_None;
!     }
! }
! 
! static PyObject *symbol_slice(pySymbol *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2))
! {
!     const char *str = flext::GetString(self->sym);
!     int len = strlen(str);
!     if(ilow < 0) {
!         ilow += len;
!         if(ilow < 0) ilow = 0;
!     }
!     if(ihigh < 0) ihigh += len;
!     if(ihigh >= len) ihigh = len-1;
! 
!     return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0);
! }
! 
! static PyObject *symbol_concat(pySymbol *self,PyObject *op)
! {
!     PyObject *nobj = symbol_slice(self); // take all
!     if(nobj) {
!         PyObject *ret = PySequence_Concat(nobj,op);
!         Py_DECREF(nobj);
!         return ret;
!     }
!     else
!         return NULL;
! }
! 
! static PyObject *symbol_repeat(pySymbol *self,int rep)
! {
!     PyObject *nobj = symbol_slice(self); // take all
!     if(nobj) {
!         PyObject *ret = PySequence_Repeat(nobj,rep);
!         Py_DECREF(nobj);
!         return ret;
!     }
!     else
!         return NULL;
! }
! 
! static PySequenceMethods symbol_as_seq = {
! 	(inquiry)symbol_length,			/* inquiry sq_length;             __len__ */
! 	(binaryfunc)symbol_concat,          /* __add__ */
! 	(intargfunc)symbol_repeat,          /* __mul__ */
! 	(intargfunc)symbol_item,			/* intargfunc sq_item;            __getitem__ */
! 	(intintargfunc)symbol_slice,		 /* intintargfunc sq_slice;        __getslice__ */
! 	NULL,		/* intobjargproc sq_ass_item;     __setitem__ */
! 	NULL,	/* intintobjargproc sq_ass_slice; __setslice__ */
! };
! 
! static PyObject *symbol_iter(PyObject *obj)
! {
!     pySymbol *self = (pySymbol *)obj;
!     PyObject *nobj = symbol_slice(self);
!     if(nobj) {
!         PyObject *it = PyObject_GetIter(nobj);
!         Py_DECREF(nobj);
!         return it;
!     }
!     else
!         return NULL;
! }
! 
! 
! 
! PyTypeObject pySymbol_Type = {
!     PyObject_HEAD_INIT(NULL)
!     0,                         /*ob_size*/
!     "Symbol",              /*tp_name*/
!     sizeof(pySymbol),          /*tp_basicsize*/
!     0,                         /*tp_itemsize*/
!     0,                         /*tp_dealloc*/
!     0,                         /*tp_print*/
!     0,                         /*tp_getattr*/
!     0,                         /*tp_setattr*/
!     0,            /*tp_compare*/
!     symbol_repr,               /*tp_repr*/
!     0,                         /*tp_as_number*/
!     &symbol_as_seq,            /*tp_as_sequence*/
!     0,                         /*tp_as_mapping*/
!     symbol_hash,               /*tp_hash */
!     0,                         /*tp_call*/
!     symbol_str,                /*tp_str*/
!     0,                         /*tp_getattro*/
!     0,                         /*tp_setattro*/
!     0,                         /*tp_as_buffer*/
!     Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/,   /*tp_flags*/
!     "Symbol objects",           /* tp_doc */
!     0,		               /* tp_traverse */
!     0,		               /* tp_clear */
!     symbol_richcompare,	       /* tp_richcompare */
!     0,		               /* tp_weaklistoffset */
!     symbol_iter,		    /* tp_iter */
!     0,		               /* tp_iternext */
!     0,                          /* tp_methods */
!     0,                          /* tp_members */
!     0,                         /* tp_getset */
!     0,                         /* tp_base */
!     0,                         /* tp_dict */
!     0,                         /* tp_descr_get */
!     0,                         /* tp_descr_set */
!     0,                         /* tp_dictoffset */
!     symbol_init,            /* tp_init */
!     0,                         /* tp_alloc */
!     symbol_new,                 /* tp_new */
! };
! 
! pySymbol *pySymbol__;
! pySymbol *pySymbol_bang;
! pySymbol *pySymbol_list;
! pySymbol *pySymbol_symbol;
! pySymbol *pySymbol_float;
! pySymbol *pySymbol_int;
! 
! 
! void initsymbol()
! {
!     if(PyType_Ready(&pySymbol_Type) < 0)
!         return;
! 
! 	Py_INCREF(&pySymbol_Type);
! 
!     // initialize predefined objects
!     pySymbol__ = symbol_newsym(flext::sym__);
!     pySymbol_bang = symbol_newsym(flext::sym_bang);
!     pySymbol_list = symbol_newsym(flext::sym_list);
!     pySymbol_symbol = symbol_newsym(flext::sym_symbol);
!     pySymbol_float = symbol_newsym(flext::sym_float);
!     pySymbol_int = symbol_newsym(flext::sym_int);
! }
! 
! 
! PyObject *pySymbol_FromSymbol(const t_symbol *sym)
! {
!     pySymbol *op;
!     if(sym == flext::sym__)
!         Py_INCREF(op = pySymbol__);
!     else if(sym == flext::sym_bang)
!         Py_INCREF(op = pySymbol_bang);
!     else if(sym == flext::sym_list)
!         Py_INCREF(op = pySymbol_list);
!     else if(sym == flext::sym_symbol)
!         Py_INCREF(op = pySymbol_symbol);
!     else if(sym == flext::sym_float)
!         Py_INCREF(op = pySymbol_float);
!     else if(sym == flext::sym_int)
!         Py_INCREF(op = pySymbol_int);
!     else
!         op = symbol_newsym(sym);
!     return (PyObject *)op;
! }

Index: pydsp.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pydsp.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** pydsp.cpp	20 Sep 2005 20:50:40 -0000	1.6
--- pydsp.cpp	7 Mar 2007 13:40:14 -0000	1.7
***************
*** 1,190 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef PY_NODSP
! 
! #include "pyext.h"
! 
! class pydsp
!     : public pyext
! {
! 	FLEXT_HEADER(pydsp,pyext)
! public:
!     pydsp(int argc,const t_atom *argv);
! 
! protected:
!     virtual bool CbDsp();
!     virtual void CbSignal();
! 
!     virtual bool DoInit();
!     virtual void DoExit();
! 
!     virtual PyObject *GetSig(int ix,bool in);
! 
!     void NewBuffers();
!     void FreeBuffers();
! 
!     PyObject *dspfun,*sigfun;
!     PyObject **buffers;
! };
! 
! FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp)
! 
! pydsp::pydsp(int argc,const t_atom *argv)
!     : pyext(argc,argv,true) 
!     , dspfun(NULL),sigfun(NULL)
! {}
! 
! bool pydsp::DoInit()
! {
!     if(!pyext::DoInit()) return false;
!     
!     if(pyobj) 
! 	{ 
!         dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref
! 	    if(!dspfun)
! 			PyErr_Clear();
! 		else if(!PyMethod_Check(dspfun)) {
!             Py_DECREF(dspfun);
! 		    dspfun = NULL;
! 		}
! 	}
!     return true;
! }
! 
! void pydsp::DoExit()
! {
!     if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; }
!     if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; }
! 
!     FreeBuffers();
! }
! 
! PyObject *arrayfrombuffer(PyObject *buf,int c,int n);
! 
! void pydsp::NewBuffers()
! {
!     int i,n = Blocksize();
!     const int ins = CntInSig(),outs = CntOutSig();
!     t_sample *const *insigs = InSig();
!     t_sample *const *outsigs = OutSig();
! 
!     // inlet/outlet count can't change so we don't have to deallocate
!     if(!buffers) {
!         int cnt = ins+outs;
!         buffers = new PyObject *[cnt];
!         memset(buffers,0,cnt*sizeof(*buffers));
!     }
! 
!     for(i = 0; i < ins; ++i) {
!         Py_XDECREF(buffers[i]);
!         PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample));
!         buffers[i] = arrayfrombuffer(b,1,n);
!         Py_DECREF(b);
!     }
!     for(i = 0; i < outs; ++i) {
!         Py_XDECREF(buffers[ins+i]);
!         if(i < ins && outsigs[i] == insigs[i]) {
!             // same vectors - share the objects!
!             buffers[ins+i] = buffers[i];
!             Py_XINCREF(buffers[i]);
!         }
!         else {
!             PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample));
!             buffers[ins+i] = arrayfrombuffer(b,1,n);
!             Py_DECREF(b);
!         }
!     }
! }
! 
! void pydsp::FreeBuffers()
! {
!     if(buffers) {
!         int cnt = CntInSig()+CntOutSig();
!         for(int i = 0; i < cnt; ++i) Py_XDECREF(buffers[i]);
!         delete[] buffers;
!         buffers = NULL;
!     }
! }
! 
! bool pydsp::CbDsp()
! {
!     if(pyobj && (CntInSig() || CntOutSig()))
!     {
!        	PyThreadState *state = PyLockSys();
! 
!         NewBuffers();
! 
! 		bool dodsp = true;
!         if(dspfun) {
!             PyObject *ret = PyObject_CallObject(dspfun,NULL);
!             if(ret) {
! 				dodsp = PyObject_IsTrue(ret) != 0;
!                 Py_DECREF(ret);
! 			}
!             else {
! #ifdef FLEXT_DEBUG
!                 PyErr_Print();
! #else
!                 PyErr_Clear();
! #endif   
!             }
!         }
! 
!         // do that here instead of where dspfun is initialized, so that
!         // _signal can be assigned in _dsp
!         // optimizations may be done there to assign the right _signal version
!         Py_XDECREF(sigfun);
! 		
! 		if(dodsp) {
! 			sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref
! 			if(!sigfun)
! 				PyErr_Clear();
! 			else if(!PyMethod_Check(sigfun)) {
! 				Py_DECREF(sigfun);
! 				sigfun = NULL;
! 			}
! 		}
! 		else
! 			sigfun = NULL;
! 
!         PyUnlock(state);
!         return sigfun != NULL;
!     }
!     else
!         // switch on dsp only if there are signal inlets or outlets
!         return false;
! }
! 
! void pydsp::CbSignal()
! {
!     PyThreadState *state = PyLockSys();
!     PyObject *ret = PyObject_CallObject(sigfun,NULL);
! 
!     if(ret) 
!         Py_DECREF(ret);
!     else {
! #ifdef FLEXT_DEBUG
!         PyErr_Print();
! #else
!         PyErr_Clear();
! #endif   
!     }
!     PyUnlock(state);
! }
! 
! PyObject *pydsp::GetSig(int ix,bool in) 
! {
!     PyObject *r = buffers[in?ix:CntInSig()+ix];
!     Py_XINCREF(r);
!     return r;
! }
! 
! #endif
--- 1,190 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef PY_NODSP
! 
! #include "pyext.h"
! 
! class pydsp
!     : public pyext
! {
! 	FLEXT_HEADER(pydsp,pyext)
! public:
!     pydsp(int argc,const t_atom *argv);
! 
! protected:
!     virtual bool CbDsp();
!     virtual void CbSignal();
! 
!     virtual bool DoInit();
!     virtual void DoExit();
! 
!     virtual PyObject *GetSig(int ix,bool in);
! 
!     void NewBuffers();
!     void FreeBuffers();
! 
!     PyObject *dspfun,*sigfun;
!     PyObject **buffers;
! };
! 
! FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp)
! 
! pydsp::pydsp(int argc,const t_atom *argv)
!     : pyext(argc,argv,true) 
!     , dspfun(NULL),sigfun(NULL)
! {}
! 
! bool pydsp::DoInit()
! {
!     if(!pyext::DoInit()) return false;
!     
!     if(pyobj) 
! 	{ 
!         dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref
! 	    if(!dspfun)
! 			PyErr_Clear();
! 		else if(!PyMethod_Check(dspfun)) {
!             Py_DECREF(dspfun);
! 		    dspfun = NULL;
! 		}
! 	}
!     return true;
! }
! 
! void pydsp::DoExit()
! {
!     if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; }
!     if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; }
! 
!     FreeBuffers();
! }
! 
! PyObject *arrayfrombuffer(PyObject *buf,int c,int n);
! 
! void pydsp::NewBuffers()
! {
!     int i,n = Blocksize();
!     const int ins = CntInSig(),outs = CntOutSig();
!     t_sample *const *insigs = InSig();
!     t_sample *const *outsigs = OutSig();
! 
!     // inlet/outlet count can't change so we don't have to deallocate
!     if(!buffers) {
!         int cnt = ins+outs;
!         buffers = new PyObject *[cnt];
!         memset(buffers,0,cnt*sizeof(*buffers));
!     }
! 
!     for(i = 0; i < ins; ++i) {
!         Py_XDECREF(buffers[i]);
!         PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample));
!         buffers[i] = arrayfrombuffer(b,1,n);
!         Py_DECREF(b);
!     }
!     for(i = 0; i < outs; ++i) {
!         Py_XDECREF(buffers[ins+i]);
!         if(i < ins && outsigs[i] == insigs[i]) {
!             // same vectors - share the objects!
!             buffers[ins+i] = buffers[i];
!             Py_XINCREF(buffers[i]);
!         }
!         else {
!             PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample));
!             buffers[ins+i] = arrayfrombuffer(b,1,n);
!             Py_DECREF(b);
!         }
!     }
! }
! 
! void pydsp::FreeBuffers()
! {
!     if(buffers) {
!         int cnt = CntInSig()+CntOutSig();
!         for(int i = 0; i < cnt; ++i) Py_XDECREF(buffers[i]);
!         delete[] buffers;
!         buffers = NULL;
!     }
! }
! 
! bool pydsp::CbDsp()
! {
!     if(pyobj && (CntInSig() || CntOutSig()))
!     {
!        	ThrState state = PyLockSys();
! 
!         NewBuffers();
! 
! 		bool dodsp = true;
!         if(dspfun) {
!             PyObject *ret = PyObject_CallObject(dspfun,NULL);
!             if(ret) {
! 				dodsp = PyObject_IsTrue(ret) != 0;
!                 Py_DECREF(ret);
! 			}
!             else {
! #ifdef FLEXT_DEBUG
!                 PyErr_Print();
! #else
!                 PyErr_Clear();
! #endif   
!             }
!         }
! 
!         // do that here instead of where dspfun is initialized, so that
!         // _signal can be assigned in _dsp
!         // optimizations may be done there to assign the right _signal version
!         Py_XDECREF(sigfun);
! 		
! 		if(dodsp) {
! 			sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref
! 			if(!sigfun)
! 				PyErr_Clear();
! 			else if(!PyMethod_Check(sigfun)) {
! 				Py_DECREF(sigfun);
! 				sigfun = NULL;
! 			}
! 		}
! 		else
! 			sigfun = NULL;
! 
!         PyUnlock(state);
!         return sigfun != NULL;
!     }
!     else
!         // switch on dsp only if there are signal inlets or outlets
!         return false;
! }
! 
! void pydsp::CbSignal()
! {
!     ThrState state = PyLockSys();
!     PyObject *ret = PyObject_CallObject(sigfun,NULL);
! 
!     if(ret) 
!         Py_DECREF(ret);
!     else {
! #ifdef FLEXT_DEBUG
!         PyErr_Print();
! #else
!         PyErr_Clear();
! #endif   
!     }
!     PyUnlock(state);
! }
! 
! PyObject *pydsp::GetSig(int ix,bool in) 
! {
!     PyObject *r = buffers[in?ix:CntInSig()+ix];
!     Py_XINCREF(r);
!     return r;
! }
! 
! #endif

Index: pymeth.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pymeth.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** pymeth.cpp	11 Aug 2005 15:00:58 -0000	1.6
--- pymeth.cpp	7 Mar 2007 13:40:14 -0000	1.7
***************
*** 1,428 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pybase.h"
! #include <map>
! 
! struct xlt { const t_symbol *from,*to; };
! 
! static const xlt xtdefs[] = { 
!     { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") },
!     { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") },
!     { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") },
!     { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") },
!     { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") },
!     { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") },
!     { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") },
!     { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") },
!     { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") },
!     { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") },
!     { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") },
!     { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") },
!     { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") },
!     { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") },
!     { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") },
!     { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") },
!     { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") },
!     { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") },
!     { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") },
!     { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") },
!     { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") },
!     { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") },
!     { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") },
!     { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") },
!     { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") },
!     { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") },
!     { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") },
!     { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") },
!     { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") },
!     { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") },
!     { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") },
!     { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") },
!     { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") },
!     { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") },
!     { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") },
!     { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") },
!     { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") },
!     { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") },
!     { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") },
!     { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") },
!     { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") },
!     { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") },
!     { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") },
!     { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") },
!     { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") },
!     { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") },
!     { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") },
!     { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") },
! 
!     { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") },
!     { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") },
!     { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") },
!     { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") },
! 
!     { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") },
!     { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") },
!     { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") },
!     { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") },
!     { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") },
!     { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") },
! 
!     { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") },
!     { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") },
! 
!     { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") },
!     { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") },
! 
!     { NULL,NULL } // sentinel
! };
! 
! typedef std::map<const t_symbol *,const t_symbol *> XTable;
! static XTable xtable;
! 
! 
! class pymeth
!     : public pybase
!     , public flext_base
! {
! 	FLEXT_HEADER_S(pymeth,flext_base,Setup)
! 
! public:
! 	pymeth(int argc,const t_atom *argv);
! 	~pymeth();
! 
! protected:
!     virtual void Exit();
! 
! 	virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv);
! 
!     void m_help();    
! 
!     void m_reload() { Reload(); }
!     void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); }
! 	void m_set(int argc,const t_atom *argv);
!     void m_dir_() { m__dir(function); }
!     void m_doc_() { m__doc(function); }
! 
! 	const t_symbol *funname;
! 	PyObject *function;
! 
! 	virtual void LoadModule();
! 	virtual void UnloadModule();
! 
! 	virtual void Load();
! 	virtual void Unload();
! 
! 	void SetFunction(const t_symbol *func);
! 	void ResetFunction();
! 
!     virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv);
! 
!     PyObject **objects;
! 
! private:
! 
!     virtual void callpy(PyObject *fun,PyObject *args);
! 
! 	static void Setup(t_classid c);
! 
! 	FLEXT_CALLBACK(m_help)
! 	FLEXT_CALLBACK(m_reload)
! 	FLEXT_CALLBACK_V(m_reload_)
! 	FLEXT_CALLBACK_V(m_set)
! 	FLEXT_CALLBACK(m_dir_)
! 	FLEXT_CALLBACK(m_doc_)
! 
! 	// callbacks
! 	FLEXT_ATTRVAR_I(detach)
! 	FLEXT_ATTRVAR_B(pymsg)
! 	FLEXT_ATTRVAR_B(respond)
! 
! 	FLEXT_CALLBACK_V(m_stop)
! 	FLEXT_CALLBACK(m_dir)
! 	FLEXT_CALLGET_V(mg_dir)
! 	FLEXT_CALLBACK(m_doc)
! 
! #ifdef FLEXT_THREADS
!     FLEXT_CALLBACK_T(tick)
! #endif
! };
! 
! FLEXT_LIB_V("pym",pymeth)
! 
! 
! void pymeth::Setup(t_classid c)
! {
! 	FLEXT_CADDMETHOD_(c,0,"doc",m_doc);
! 	FLEXT_CADDMETHOD_(c,0,"dir",m_dir);
! #ifdef FLEXT_THREADS
! 	FLEXT_CADDATTR_VAR1(c,"detach",detach);
! 	FLEXT_CADDMETHOD_(c,0,"stop",m_stop);
! #endif
! 
! 	FLEXT_CADDMETHOD_(c,0,"help",m_help);
! 	FLEXT_CADDMETHOD_(c,0,"reload",m_reload_);
!     FLEXT_CADDMETHOD_(c,0,"reload.",m_reload);
! 	FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_);
! 	FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
! 
! 	FLEXT_CADDMETHOD_(c,0,"set",m_set);
! 
!   	FLEXT_CADDATTR_VAR1(c,"py",pymsg);
!   	FLEXT_CADDATTR_VAR1(c,"respond",respond);
! 
!     // init translation map
!     for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to;
! }
! 
! pymeth::pymeth(int argc,const t_atom *argv)
!     : funname(NULL)
!     , function(NULL)
!     , objects(NULL)
! { 
! #ifdef FLEXT_THREADS
!     FLEXT_ADDTIMER(stoptmr,tick);
! #endif
! 
! 	PyThreadState *state = PyLockSys();
! 
!     int inlets;
!     if(argc && CanbeInt(*argv)) {
!         inlets = GetAInt(*argv);
!         if(inlets < 1) inlets = 1;
!         argv++,argc--;
!     }
!     else inlets = 1;
! 
!     objects = new PyObject *[inlets];
!     for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); }
! 
!     if(inlets <= 0) InitProblem();
! 
!     AddInAnything(1+(inlets < 0?1:inlets));
! 	AddOutAnything();  
! 
! 	Register(GetRegistry(REGNAME));
! 
!     if(argc) {
!         const t_symbol *funnm = GetASymbol(*argv);
!         argv++,argc--;
! 
!         if(funnm)
! 	        SetFunction(funnm);
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid function name");
!     }
! 
! 	if(argc) args(argc,argv);
! 
!     Report();
! 
! 	PyUnlock(state);
! }
! 
! pymeth::~pymeth() 
! {
!     if(objects) {
!         for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]);
!         delete[] objects;
!     }
! 
!     PyThreadState *state = PyLockSys();
! 	Unregister(GetRegistry(REGNAME));
!     Report();
! 	PyUnlock(state);
! }
! 
! void pymeth::Exit() 
! { 
!     pybase::Exit(); 
!     flext_base::Exit(); 
! }
! 
! void pymeth::m_set(int argc,const t_atom *argv)
! {
! 	PyThreadState *state = PyLockSys();
! 
!     // function name has precedence
! 	if(argc >= 2) {
! 	    const char *sn = GetAString(*argv);
! 	    ++argv,--argc;
! 
!         if(sn) {
! 		    if(!module || !strcmp(sn,PyModule_GetName(module))) {
! 			    ImportModule(sn);
! 			    Register(GetRegistry(REGNAME));
! 		    }
!         }
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid module name");
! 	}
! 
!     if(argc) {
! 	    const t_symbol *fn = GetASymbol(*argv);
!         if(fn)
! 	        SetFunction(fn);
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid function name");
!     }
! 
!     Report();
! 
! 	PyUnlock(state);
! }
! 
! void pymeth::m_help()
! {
! 	post("");
! 	post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION);
! #ifdef FLEXT_DEBUG
! 	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
! #endif
! 
! 	post("Arguments: %s [method name] {args...}",thisName());
! 
! 	post("Inlet 1:messages to control the py object");
! 	post("      2:call python function with message as argument(s)");
! 	post("Outlet: 1:return values from python function");	
! 	post("Methods:");
! 	post("\thelp: shows this help");
! 	post("\tbang: call script without arguments");
! 	post("\tset [script name] [function name]: set (script and) function name");
! 	post("\treload {args...}: reload python script");
! 	post("\treload. : reload with former arguments");
! 	post("\tdoc: display module doc string");
! 	post("\tdoc+: display function doc string");
! 	post("\tdir: dump module dictionary");
! 	post("\tdir+: dump function dictionary");
! #ifdef FLEXT_THREADS
! 	post("\tdetach 0/1/2: detach threads");
! 	post("\tstop {wait time (ms)}: stop threads");
! #endif
! 	post("");
! }
! 
! void pymeth::ResetFunction()
! {
!     Py_XDECREF(function);
!     function = NULL;
!     
!     if(funname && objects[0] != Py_None) {
!         function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference
!         if(!function) 
!             PyErr_SetString(PyExc_AttributeError,"Method not found");
!     }
! 
!     // exception could be set here
! }
! 
! void pymeth::SetFunction(const t_symbol *func)
! {
!     // look for method name in translation table
!     XTable::iterator it = xtable.find(func);
!     funname = it == xtable.end()?func:it->second;
! 
!     ResetFunction();
! }
! 
! 
! void pymeth::LoadModule() 
! {
!     SetFunction(funname);
! }
! 
! void pymeth::UnloadModule() 
! {
! }
! 
! void pymeth::Load()
! {
! 	ResetFunction();
! }
! 
! void pymeth::Unload()
! {
!     SetFunction(NULL);
! }
! 
! void pymeth::callpy(PyObject *fun,PyObject *args)
! {
!     PyObject *ret = PyObject_CallObject(fun,args); 
!     if(ret) {
!         OutObject(this,0,ret); // exception might be raised here
!         Py_DECREF(ret);
!     }
! } 
! 
! bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
! {
!     if(n == 0 && s != sym_bang) 
!         return flext_base::CbMethodResort(n,s,argc,argv);
! 
!     PyThreadState *state = PyLockSys();
! 
!     bool ret = false;
!  
!     if(n >= 1) {
!         // store args
!         PyObject *&obj = objects[n-1];
!         Py_DECREF(obj);
!         obj = MakePyArg(s,argc,argv); // steal reference
! 
!         if(n > 1) ret = true; // just store, don't trigger
!     }
! 
!     if(!ret) {
!         if(function) {
!             PyObject *self = PyMethod_Self(function);
!             PyErr_Clear();
!             if(!self || self->ob_type != objects[0]->ob_type)
!                 // type has changed, search for new method
!                 ResetFunction();
!             else if(self != objects[0]) {
!                 // type hasn't changed, but object has
!                 PyObject *f = function;
!                 function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f));
!                 Py_DECREF(f);
!             }
!         }
!         else
!             ResetFunction();
! 
!         if(function) {
!             Py_INCREF(function);
! 
!             int inlets = CntIn()-1;
!             PyObject *pargs = PyTuple_New(inlets-1);
!             for(int i = 1; i < inlets; ++i) {
!                 Py_INCREF(objects[i]);
!     		    PyTuple_SET_ITEM(pargs,i-1,objects[i]);
!             }
! 
!             gencall(function,pargs); // references are stolen
!             ret = true;
!         }
! 	    else
! 		    PyErr_SetString(PyExc_RuntimeError,"No function set");
! 
!         Report();
!     }
! 
!     PyUnlock(state);
! 
!     Respond(ret);
! 
!     return ret;
! }
! 
! void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv)
! {
!     ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv);
! }
--- 1,428 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pybase.h"
! #include <map>
! 
! struct xlt { const t_symbol *from,*to; };
! 
! static const xlt xtdefs[] = { 
!     { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") },
!     { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") },
!     { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") },
!     { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") },
!     { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") },
!     { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") },
!     { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") },
!     { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") },
!     { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") },
!     { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") },
!     { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") },
!     { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") },
!     { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") },
!     { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") },
!     { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") },
!     { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") },
!     { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") },
!     { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") },
!     { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") },
!     { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") },
!     { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") },
!     { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") },
!     { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") },
!     { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") },
!     { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") },
!     { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") },
!     { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") },
!     { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") },
!     { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") },
!     { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") },
!     { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") },
!     { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") },
!     { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") },
!     { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") },
!     { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") },
!     { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") },
!     { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") },
!     { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") },
!     { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") },
!     { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") },
!     { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") },
!     { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") },
!     { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") },
!     { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") },
!     { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") },
!     { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") },
!     { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") },
!     { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") },
! 
!     { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") },
!     { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") },
!     { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") },
!     { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") },
! 
!     { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") },
!     { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") },
!     { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") },
!     { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") },
!     { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") },
!     { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") },
! 
!     { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") },
!     { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") },
! 
!     { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") },
!     { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") },
! 
!     { NULL,NULL } // sentinel
! };
! 
! typedef std::map<const t_symbol *,const t_symbol *> XTable;
! static XTable xtable;
! 
! 
! class pymeth
!     : public pybase
!     , public flext_base
! {
! 	FLEXT_HEADER_S(pymeth,flext_base,Setup)
! 
! public:
! 	pymeth(int argc,const t_atom *argv);
! 	~pymeth();
! 
! protected:
!     virtual void Exit();
! 
! 	virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv);
! 
!     void m_help();    
! 
!     void m_reload() { Reload(); }
!     void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); }
! 	void m_set(int argc,const t_atom *argv);
!     void m_dir_() { m__dir(function); }
!     void m_doc_() { m__doc(function); }
! 
! 	const t_symbol *funname;
! 	PyObject *function;
! 
! 	virtual void LoadModule();
! 	virtual void UnloadModule();
! 
! 	virtual void Load();
! 	virtual void Unload();
! 
! 	void SetFunction(const t_symbol *func);
! 	void ResetFunction();
! 
!     virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv);
! 
!     PyObject **objects;
! 
! private:
! 
!     virtual void callpy(PyObject *fun,PyObject *args);
! 
! 	static void Setup(t_classid c);
! 
! 	FLEXT_CALLBACK(m_help)
! 	FLEXT_CALLBACK(m_reload)
! 	FLEXT_CALLBACK_V(m_reload_)
! 	FLEXT_CALLBACK_V(m_set)
! 	FLEXT_CALLBACK(m_dir_)
! 	FLEXT_CALLBACK(m_doc_)
! 
! 	// callbacks
! 	FLEXT_ATTRVAR_I(detach)
! 	FLEXT_ATTRVAR_B(pymsg)
! 	FLEXT_ATTRVAR_B(respond)
! 
! 	FLEXT_CALLBACK_V(m_stop)
! 	FLEXT_CALLBACK(m_dir)
! 	FLEXT_CALLGET_V(mg_dir)
! 	FLEXT_CALLBACK(m_doc)
! 
! #ifdef FLEXT_THREADS
!     FLEXT_CALLBACK_T(tick)
! #endif
! };
! 
! FLEXT_LIB_V("pym",pymeth)
! 
! 
! void pymeth::Setup(t_classid c)
! {
! 	FLEXT_CADDMETHOD_(c,0,"doc",m_doc);
! 	FLEXT_CADDMETHOD_(c,0,"dir",m_dir);
! #ifdef FLEXT_THREADS
! 	FLEXT_CADDATTR_VAR1(c,"detach",detach);
! 	FLEXT_CADDMETHOD_(c,0,"stop",m_stop);
! #endif
! 
! 	FLEXT_CADDMETHOD_(c,0,"help",m_help);
! 	FLEXT_CADDMETHOD_(c,0,"reload",m_reload_);
!     FLEXT_CADDMETHOD_(c,0,"reload.",m_reload);
! 	FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_);
! 	FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
! 
! 	FLEXT_CADDMETHOD_(c,0,"set",m_set);
! 
!   	FLEXT_CADDATTR_VAR1(c,"py",pymsg);
!   	FLEXT_CADDATTR_VAR1(c,"respond",respond);
! 
!     // init translation map
!     for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to;
! }
! 
! pymeth::pymeth(int argc,const t_atom *argv)
!     : funname(NULL)
!     , function(NULL)
!     , objects(NULL)
! { 
! #ifdef FLEXT_THREADS
!     FLEXT_ADDTIMER(stoptmr,tick);
! #endif
! 
! 	ThrState state = PyLockSys();
! 
!     int inlets;
!     if(argc && CanbeInt(*argv)) {
!         inlets = GetAInt(*argv);
!         if(inlets < 1) inlets = 1;
!         argv++,argc--;
!     }
!     else inlets = 1;
! 
!     objects = new PyObject *[inlets];
!     for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); }
! 
!     if(inlets <= 0) InitProblem();
! 
!     AddInAnything(1+(inlets < 0?1:inlets));
! 	AddOutAnything();  
! 
! 	Register(GetRegistry(REGNAME));
! 
!     if(argc) {
!         const t_symbol *funnm = GetASymbol(*argv);
!         argv++,argc--;
! 
!         if(funnm)
! 	        SetFunction(funnm);
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid function name");
!     }
! 
! 	if(argc) args(argc,argv);
! 
!     Report();
! 
! 	PyUnlock(state);
! }
! 
! pymeth::~pymeth() 
! {
!     if(objects) {
!         for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]);
!         delete[] objects;
!     }
! 
!     ThrState state = PyLockSys();
! 	Unregister(GetRegistry(REGNAME));
!     Report();
! 	PyUnlock(state);
! }
! 
! void pymeth::Exit() 
! { 
!     pybase::Exit(); 
!     flext_base::Exit(); 
! }
! 
! void pymeth::m_set(int argc,const t_atom *argv)
! {
! 	ThrState state = PyLockSys();
! 
!     // function name has precedence
! 	if(argc >= 2) {
! 	    const char *sn = GetAString(*argv);
! 	    ++argv,--argc;
! 
!         if(sn) {
! 		    if(!module || !strcmp(sn,PyModule_GetName(module))) {
! 			    ImportModule(sn);
! 			    Register(GetRegistry(REGNAME));
! 		    }
!         }
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid module name");
! 	}
! 
!     if(argc) {
! 	    const t_symbol *fn = GetASymbol(*argv);
!         if(fn)
! 	        SetFunction(fn);
!         else
!             PyErr_SetString(PyExc_ValueError,"Invalid function name");
!     }
! 
!     Report();
! 
! 	PyUnlock(state);
! }
! 
! void pymeth::m_help()
! {
! 	post("");
! 	post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION);
! #ifdef FLEXT_DEBUG
! 	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
! #endif
! 
! 	post("Arguments: %s [method name] {args...}",thisName());
! 
! 	post("Inlet 1:messages to control the py object");
! 	post("      2:call python function with message as argument(s)");
! 	post("Outlet: 1:return values from python function");	
! 	post("Methods:");
! 	post("\thelp: shows this help");
! 	post("\tbang: call script without arguments");
! 	post("\tset [script name] [function name]: set (script and) function name");
! 	post("\treload {args...}: reload python script");
! 	post("\treload. : reload with former arguments");
! 	post("\tdoc: display module doc string");
! 	post("\tdoc+: display function doc string");
! 	post("\tdir: dump module dictionary");
! 	post("\tdir+: dump function dictionary");
! #ifdef FLEXT_THREADS
! 	post("\tdetach 0/1/2: detach threads");
! 	post("\tstop {wait time (ms)}: stop threads");
! #endif
! 	post("");
! }
! 
! void pymeth::ResetFunction()
! {
!     Py_XDECREF(function);
!     function = NULL;
!     
!     if(funname && objects[0] != Py_None) {
!         function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference
!         if(!function) 
!             PyErr_SetString(PyExc_AttributeError,"Method not found");
!     }
! 
!     // exception could be set here
! }
! 
! void pymeth::SetFunction(const t_symbol *func)
! {
!     // look for method name in translation table
!     XTable::iterator it = xtable.find(func);
!     funname = it == xtable.end()?func:it->second;
! 
!     ResetFunction();
! }
! 
! 
! void pymeth::LoadModule() 
! {
!     SetFunction(funname);
! }
! 
! void pymeth::UnloadModule() 
! {
! }
! 
! void pymeth::Load()
! {
! 	ResetFunction();
! }
! 
! void pymeth::Unload()
! {
!     SetFunction(NULL);
! }
! 
! void pymeth::callpy(PyObject *fun,PyObject *args)
! {
!     PyObject *ret = PyObject_CallObject(fun,args); 
!     if(ret) {
!         OutObject(this,0,ret); // exception might be raised here
!         Py_DECREF(ret);
!     }
! } 
! 
! bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
! {
!     if(n == 0 && s != sym_bang) 
!         return flext_base::CbMethodResort(n,s,argc,argv);
! 
!     ThrState state = PyLockSys();
! 
!     bool ret = false;
!  
!     if(n >= 1) {
!         // store args
!         PyObject *&obj = objects[n-1];
!         Py_DECREF(obj);
!         obj = MakePyArg(s,argc,argv); // steal reference
! 
!         if(n > 1) ret = true; // just store, don't trigger
!     }
! 
!     if(!ret) {
!         if(function) {
!             PyObject *self = PyMethod_Self(function);
!             PyErr_Clear();
!             if(!self || self->ob_type != objects[0]->ob_type)
!                 // type has changed, search for new method
!                 ResetFunction();
!             else if(self != objects[0]) {
!                 // type hasn't changed, but object has
!                 PyObject *f = function;
!                 function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f));
!                 Py_DECREF(f);
!             }
!         }
!         else
!             ResetFunction();
! 
!         if(function) {
!             Py_INCREF(function);
! 
!             int inlets = CntIn()-1;
!             PyObject *pargs = PyTuple_New(inlets-1);
!             for(int i = 1; i < inlets; ++i) {
!                 Py_INCREF(objects[i]);
!     		    PyTuple_SET_ITEM(pargs,i-1,objects[i]);
!             }
! 
!             gencall(function,pargs); // references are stolen
!             ret = true;
!         }
! 	    else
! 		    PyErr_SetString(PyExc_RuntimeError,"No function set");
! 
!         Report();
!     }
! 
!     PyUnlock(state);
! 
!     Respond(ret);
! 
!     return ret;
! }
! 
! void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv)
! {
!     ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv);
! }

Index: pybundle.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pybundle.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** pybundle.cpp	12 Dec 2005 13:55:28 -0000	1.1
--- pybundle.cpp	7 Mar 2007 13:40:14 -0000	1.2
***************
*** 1,232 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyprefix.h"
! #include "pybundle.h"
! #include "pyext.h"
! 
! static PyObject *bundle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
! {
!     pyBundle *self = (pyBundle *)pyBundle_Type.tp_alloc(&pyBundle_Type, 0);
!     if(self) self->bundle = flext::MsgNew();
!     return (PyObject *)self;
! }
! 
! static int bundle_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
! 
!     int len = PySequence_Length(args);
!     if(len) {
!         PyErr_SetString(PyExc_TypeError,"no arguments expected");
!         return -1;
!     }
! 
!     return 0;
! }
! 
! static void bundle_dealloc(PyObject *obj)
! {
!     pyBundle *self = (pyBundle *)obj;
!     if(self->bundle) flext::MsgFree(self->bundle);
!     obj->ob_type->tp_free(obj);
! }
! 
! static PyObject *bundle_send(PyObject *obj)
! {
!     pyBundle *self = (pyBundle *)obj;
!     if(self->bundle) {
!         flext::ToOutMsg(self->bundle);
!         self->bundle = NULL;
! 
!         Py_INCREF(obj);
!         return obj;
!     }
!     else {
!         PyErr_SetString(PyExc_RuntimeError,"already sent");
!         return NULL;
!     }
! }
! 
! static PyObject *bundle_repr(PyObject *self)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
!     return (PyObject *)PyString_FromFormat("<Bundle %p>",pyBundle_AS_BUNDLE(self));
! }
! 
! static PyObject *bundle_str(PyObject *self)
! {
!     return bundle_repr(self);
! }
! 
! static PyObject *bundle_richcompare(PyObject *a,PyObject *b,int cmp)
! {
!     if(pyBundle_Check(a) && pyBundle_Check(b)) {
!         const flext::MsgBundle *abnd = pyBundle_AS_BUNDLE(a);
!         const flext::MsgBundle *bbnd = pyBundle_AS_BUNDLE(b);
!         bool ret;
!         switch(cmp) {
!             case Py_LT: ret = abnd < bbnd; break;
!             case Py_LE: ret = abnd <= bbnd; break;
!             case Py_EQ: ret = abnd == bbnd; break;
!             case Py_NE: ret = abnd != bbnd; break;
!             case Py_GT: ret = abnd > bbnd; break;
!             case Py_GE: ret = abnd >= bbnd; break;
!         }
!         return PyBool_FromLong(ret);
!     }
  	Py_INCREF(Py_NotImplemented);
  	return Py_NotImplemented;
! }
! 
! static long bundle_hash(PyObject *self)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
!     return (long)pyBundle_AS_BUNDLE(self);
! }
! 
! 
! static PyObject *bundle_append(PyObject *self,PyObject *args)
! {
!     flext::MsgBundle *b = pyBundle_AS_BUNDLE(self);
!     if(b) {
!         int sz = PyTuple_GET_SIZE(args),offs = 0;
!         PyObject *tg,*outl;
!         pyext *ext = NULL;
!         const t_symbol *recv;
!         int o;
! 
!         if(sz > 2 &&
! 		    (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && 
! 		    (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl)
!         ) {
!             // Sending to outlet
!             ext = pyext::GetThis(tg);
!             o = PyInt_AS_LONG(outl);
! 
!     		if(o < 1 || o > ext->Outlets()) {
!                 PyErr_SetString(PyExc_ValueError,"Outlet index out of range");
!                 return NULL;
!             }
! 
!             offs += 2;
!         }
!         else if(sz > 1 &&
! 		    (tg = PyTuple_GET_ITEM(args,0)) != NULL && (recv = pyObject_AsSymbol(tg)) != NULL
!         ) {
!             // Sending to receiver
!             offs++;
!         }
!         else {
!             // not recognized
!     		PyErr_SetString(PyExc_SyntaxError,"Unrecognized arguments");
!             return NULL;
!         }
! 
!         PyObject *val;
!         if(sz-offs == 1) {
!             val = PyTuple_GET_ITEM(args,offs); // borrow reference
!             Py_INCREF(val);
!         }
!         else
!             val = PyTuple_GetSlice(args,offs,sz);  // new ref
! 
!         flext::AtomListStatic<16> lst;
!         const t_symbol *sym = pybase::GetPyArgs(lst,val);
! 		Py_DECREF(val);
!         
! 		if(sym) {
!             if(ext) {
!                 FLEXT_ASSERT(outl);
!                 ext->MsgAddAnything(b,o-1,sym,lst.Count(),lst.Atoms());
!             }
!             else {
!                 FLEXT_ASSERT(sym);
!                 if(!flext::MsgForward(b,recv,sym,lst.Count(),lst.Atoms())) {
!     		        PyErr_SetString(PyExc_ValueError,"Receiver not found");
!                     return NULL;
!                 }
!             }
! 
!             Py_INCREF(Py_None);
!             return Py_None;
! 		}
!         else {
!             FLEXT_ASSERT(PyErr_Occurred());
!             return NULL;
!         }
! 
!         Py_INCREF(self);
!         return self;
!     }
!     else {
! 		PyErr_SetString(PyExc_RuntimeError,"Invalid bundle");
!         return NULL;
!     }
! }
! 
! static PyMethodDef bundle_methods[] = {
!     {"append", (PyCFunction)bundle_append,METH_VARARGS,"Append message to bundle"},
!     {"send", (PyCFunction)bundle_send,METH_NOARGS,"Send bundle"},
!     {NULL}  /* Sentinel */
! };
! 
! 
! 
! PyTypeObject pyBundle_Type = {
!     PyObject_HEAD_INIT(NULL)
!     0,                         /*ob_size*/
!     "Bundle",              /*tp_name*/
!     sizeof(pyBundle),          /*tp_basicsize*/
!     0,                         /*tp_itemsize*/
!     bundle_dealloc,             /*tp_dealloc*/
!     0,                         /*tp_print*/
!     0,                         /*tp_getattr*/
!     0,                         /*tp_setattr*/
!     0,            /*tp_compare*/
!     bundle_repr,               /*tp_repr*/
!     0,                         /*tp_as_number*/
!     0,            /*tp_as_sequence*/
!     0,                         /*tp_as_mapping*/
!     bundle_hash,               /*tp_hash */
!     0,                         /*tp_call*/
!     bundle_str,                /*tp_str*/
!     0,                         /*tp_getattro*/
!     0,                         /*tp_setattro*/
!     0,                         /*tp_as_buffer*/
!     Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/,   /*tp_flags*/
!     "Bundle objects",           /* tp_doc */
!     0,		               /* tp_traverse */
!     0,		               /* tp_clear */
!     bundle_richcompare,	       /* tp_richcompare */
!     0,		               /* tp_weaklistoffset */
!     0,		    /* tp_iter */
!     0,		               /* tp_iternext */
!     bundle_methods,            /* tp_methods */
!     0,                          /* tp_members */
!     0,                         /* tp_getset */
!     0,                         /* tp_base */
!     0,                         /* tp_dict */
!     0,                         /* tp_descr_get */
!     0,                         /* tp_descr_set */
!     0,                         /* tp_dictoffset */
!     bundle_init,            /* tp_init */
!     0,                         /* tp_alloc */
!     bundle_new,                 /* tp_new */
! };
! 
! 
! void initbundle()
! {
!     if(PyType_Ready(&pyBundle_Type) < 0)
!         FLEXT_ASSERT(false);
!     else
!         Py_INCREF(&pyBundle_Type);
! }
--- 1,232 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #include "pyprefix.h"
! #include "pybundle.h"
! #include "pyext.h"
! 
! static PyObject *bundle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
! {
!     pyBundle *self = (pyBundle *)pyBundle_Type.tp_alloc(&pyBundle_Type, 0);
!     if(self) self->bundle = flext::MsgNew();
!     return (PyObject *)self;
! }
! 
! static int bundle_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
! 
!     int len = PySequence_Length(args);
!     if(len) {
!         PyErr_SetString(PyExc_TypeError,"no arguments expected");
!         return -1;
!     }
! 
!     return 0;
! }
! 
! static void bundle_dealloc(PyObject *obj)
! {
!     pyBundle *self = (pyBundle *)obj;
!     if(self->bundle) flext::MsgFree(self->bundle);
!     obj->ob_type->tp_free(obj);
! }
! 
! static PyObject *bundle_send(PyObject *obj)
! {
!     pyBundle *self = (pyBundle *)obj;
!     if(self->bundle) {
!         flext::ToOutMsg(self->bundle);
!         self->bundle = NULL;
! 
!         Py_INCREF(obj);
!         return obj;
!     }
!     else {
!         PyErr_SetString(PyExc_RuntimeError,"already sent");
!         return NULL;
!     }
! }
! 
! static PyObject *bundle_repr(PyObject *self)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
!     return (PyObject *)PyString_FromFormat("<Bundle %p>",pyBundle_AS_BUNDLE(self));
! }
! 
! static PyObject *bundle_str(PyObject *self)
! {
!     return bundle_repr(self);
! }
! 
! static PyObject *bundle_richcompare(PyObject *a,PyObject *b,int cmp)
! {
!     if(pyBundle_Check(a) && pyBundle_Check(b)) {
!         const flext::MsgBundle *abnd = pyBundle_AS_BUNDLE(a);
!         const flext::MsgBundle *bbnd = pyBundle_AS_BUNDLE(b);
!         bool ret;
!         switch(cmp) {
!             case Py_LT: ret = abnd < bbnd; break;
!             case Py_LE: ret = abnd <= bbnd; break;
!             case Py_EQ: ret = abnd == bbnd; break;
!             case Py_NE: ret = abnd != bbnd; break;
!             case Py_GT: ret = abnd > bbnd; break;
!             case Py_GE: ret = abnd >= bbnd; break;
!         }
!         return PyBool_FromLong(ret);
!     }
  	Py_INCREF(Py_NotImplemented);
  	return Py_NotImplemented;
! }
! 
! static long bundle_hash(PyObject *self)
! {
!     FLEXT_ASSERT(pyBundle_Check(self));
!     return (long)pyBundle_AS_BUNDLE(self);
! }
! 
! 
! static PyObject *bundle_append(PyObject *self,PyObject *args)
! {
!     flext::MsgBundle *b = pyBundle_AS_BUNDLE(self);
!     if(b) {
!         int sz = PyTuple_GET_SIZE(args),offs = 0;
!         PyObject *tg,*outl;
!         pyext *ext = NULL;
!         const t_symbol *recv;
!         int o;
! 
!         if(sz > 2 &&
! 		    (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && 
! 		    (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl)
!         ) {
!             // Sending to outlet
!             ext = pyext::GetThis(tg);
!             o = PyInt_AS_LONG(outl);
! 
!     		if(o < 1 || o > ext->Outlets()) {
!                 PyErr_SetString(PyExc_ValueError,"Outlet index out of range");
!                 return NULL;
!             }
! 
!             offs += 2;
!         }
!         else if(sz > 1 &&
! 		    (tg = PyTuple_GET_ITEM(args,0)) != NULL && (recv = pyObject_AsSymbol(tg)) != NULL
!         ) {
!             // Sending to receiver
!             offs++;
!         }
!         else {
!             // not recognized
!     		PyErr_SetString(PyExc_SyntaxError,"Unrecognized arguments");
!             return NULL;
!         }
! 
!         PyObject *val;
!         if(sz-offs == 1) {
!             val = PyTuple_GET_ITEM(args,offs); // borrow reference
!             Py_INCREF(val);
!         }
!         else
!             val = PyTuple_GetSlice(args,offs,sz);  // new ref
! 
!         flext::AtomListStatic<16> lst;
!         const t_symbol *sym = pybase::GetPyArgs(lst,val);
! 		Py_DECREF(val);
!         
! 		if(sym) {
!             if(ext) {
!                 FLEXT_ASSERT(outl);
!                 ext->MsgAddAnything(b,o-1,sym,lst.Count(),lst.Atoms());
!             }
!             else {
!                 FLEXT_ASSERT(sym);
!                 if(!flext::MsgForward(b,recv,sym,lst.Count(),lst.Atoms())) {
!     		        PyErr_SetString(PyExc_ValueError,"Receiver not found");
!                     return NULL;
!                 }
!             }
! 
!             Py_INCREF(Py_None);
!             return Py_None;
! 		}
!         else {
!             FLEXT_ASSERT(PyErr_Occurred());
!             return NULL;
!         }
! 
!         Py_INCREF(self);
!         return self;
!     }
!     else {
! 		PyErr_SetString(PyExc_RuntimeError,"Invalid bundle");
!         return NULL;
!     }
! }
! 
! static PyMethodDef bundle_methods[] = {
!     {"append", (PyCFunction)bundle_append,METH_VARARGS,"Append message to bundle"},
!     {"send", (PyCFunction)bundle_send,METH_NOARGS,"Send bundle"},
!     {NULL}  /* Sentinel */
! };
! 
! 
! 
! PyTypeObject pyBundle_Type = {
!     PyObject_HEAD_INIT(NULL)
!     0,                         /*ob_size*/
!     "Bundle",              /*tp_name*/
!     sizeof(pyBundle),          /*tp_basicsize*/
!     0,                         /*tp_itemsize*/
!     bundle_dealloc,             /*tp_dealloc*/
!     0,                         /*tp_print*/
!     0,                         /*tp_getattr*/
!     0,                         /*tp_setattr*/
!     0,            /*tp_compare*/
!     bundle_repr,               /*tp_repr*/
!     0,                         /*tp_as_number*/
!     0,            /*tp_as_sequence*/
!     0,                         /*tp_as_mapping*/
!     bundle_hash,               /*tp_hash */
!     0,                         /*tp_call*/
!     bundle_str,                /*tp_str*/
!     0,                         /*tp_getattro*/
!     0,                         /*tp_setattro*/
!     0,                         /*tp_as_buffer*/
!     Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/,   /*tp_flags*/
!     "Bundle objects",           /* tp_doc */
!     0,		               /* tp_traverse */
!     0,		               /* tp_clear */
!     bundle_richcompare,	       /* tp_richcompare */
!     0,		               /* tp_weaklistoffset */
!     0,		    /* tp_iter */
!     0,		               /* tp_iternext */
!     bundle_methods,            /* tp_methods */
!     0,                          /* tp_members */
!     0,                         /* tp_getset */
!     0,                         /* tp_base */
!     0,                         /* tp_dict */
!     0,                         /* tp_descr_get */
!     0,                         /* tp_descr_set */
!     0,                         /* tp_dictoffset */
!     bundle_init,            /* tp_init */
!     0,                         /* tp_alloc */
!     bundle_new,                 /* tp_new */
! };
! 
! 
! void initbundle()
! {
!     if(PyType_Ready(&pyBundle_Type) < 0)
!         FLEXT_ASSERT(false);
!     else
!         Py_INCREF(&pyBundle_Type);
! }

Index: pybase.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** pybase.h	3 Aug 2006 16:33:37 -0000	1.12
--- pybase.h	7 Mar 2007 13:40:14 -0000	1.13
***************
*** 1,228 ****
! /* 
! 
! py/pyext - python script object for PD and MaxMSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYBASE_H
! #define __PYBASE_H
! 
! #include "main.h"
! #include "pysymbol.h"
! #include "pybuffer.h"
! #include "pybundle.h"
! 
! class pybase
!     : public flext
! {
! public:
! 	pybase();
! 	virtual ~pybase();
! 
!     void Exit();
! 
! 	static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1);
! 	static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv);
! 	static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0);
! 	static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue);
! 
!     static void lib_setup();
! 
! protected:
! 
!     virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv) = 0;
! 
!     void m__dir(PyObject *obj);
! 	void m__doc(PyObject *obj);
! 
!     void m_dir() { m__dir(module); }
!     void mg_dir(AtomList &lst) { m__dir(module); }
!     void m_doc() { m__doc(dict); }
! 
!     std::string modname; // module name
! 	PyObject *module,*dict; // object module and associated dictionary
! 
! 	static const char *py_doc;
! 
!     void GetDir(PyObject *obj,AtomList &lst);
! 
! 	AtomList args;
! 
!     void AddCurrentPath(flext_base *o);
! 	void SetArgs();
! 
!     bool OutObject(flext_base *ext,int o,PyObject *obj);
! 
!     // reload module and all connected objects
!     void Reload();
! 
! 	bool ImportModule(const char *name);
! 	void UnimportModule();
! 	bool ReloadModule();
! 
!     // Get module registry
! 	PyObject *GetRegistry(const char *regname);
!     // Set module registry
! 	void SetRegistry(const char *regname,PyObject *reg);
! 
!     // Register object
! 	void Register(PyObject *reg);
!     // Unregister object
! 	void Unregister(PyObject *reg);
! 
! 	virtual void LoadModule() = 0;
! 	virtual void UnloadModule() = 0;
! 
! 	virtual void Load() = 0;
! 	virtual void Unload() = 0;
! 
!     void OpenEditor();
! 
!     void Respond(bool b)
!     { 
!         if(respond) { 
!             t_atom a; 
!             SetBool(a,b); 
!             DumpOut(sym_response,1,&a); 
!         } 
!     }
! 
!     void Report() { while(PyErr_Occurred()) PyErr_Print(); }
! 
! 	static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
! 	static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; }
! 
! //	enum retval { nothing,atom,sequ };
! 
! 	// --- module stuff -----
! 
! 	static PyObject *module_obj,*module_dict;
! 	static PyObject *builtins_obj,*builtins_dict;
! 	static PyMethodDef func_tbl[];
! 
! 	static PyObject *py__doc__(PyObject *,PyObject *args);
! 	static PyObject *py_send(PyObject *,PyObject *args);
! #ifdef FLEXT_THREADS
! 	static PyObject *py_priority(PyObject *,PyObject *args);
! #endif
! 
! 	static PyObject *py_arraysupport(PyObject *,PyObject *args);
! 	static PyObject *py_samplerate(PyObject *,PyObject *args);
! 	static PyObject *py_blocksize(PyObject *,PyObject *args);
! 
! #if FLEXT_SYS == FLEXT_SYS_PD
! 	static PyObject *py_getvalue(PyObject *,PyObject *args);
! 	static PyObject *py_setvalue(PyObject *,PyObject *args);
! #endif
! 
!     static PyObject *py_list(PyObject *,PyObject *args);
!     static PyObject *py_tuple(PyObject *,PyObject *args);
! 
! 	// ----thread stuff ------------
! 
! 	virtual void m_stop(int argc,const t_atom *argv);
! 
! 	bool respond;
! #ifdef FLEXT_THREADS
! 	int thrcount;
!     bool shouldexit;
! 	int stoptick;
!     Timer stoptmr;
! 
! 	void tick(void *);
! #endif
! 
!     int detach;
!     bool pymsg;
! 
!     bool gencall(PyObject *fun,PyObject *args);
! 
!     bool docall(PyObject *fun,PyObject *args)
!     {
!         callpy(fun,args);
!         if(PyErr_Occurred()) { 
!             exchandle(); 
!             return false; 
!         }
!         else 
!             return true;
!     }
! 
!     virtual void callpy(PyObject *fun,PyObject *args) = 0;
! 
!     void exchandle();
! 
!     static bool collect();
! 
! protected:
! 
! #ifdef FLEXT_THREADS
!     static void thrworker(thr_params *data); 
! 
!     bool qucall(PyObject *fun,PyObject *args)
!     {
!         FifoEl *el = qufifo.New();
!         el->Set(this,fun,args);
!         qufifo.Put(el);
!         qucond.Signal();
!         return true;
!     }
! 
!     static void quworker(thr_params *);
!     void erasethreads();
! 
!     static PyFifo qufifo;
!     static ThrCond qucond;
!     static PyThreadState *pythrsys;
! #endif
! 
!     static const t_symbol *sym_fint; // float or int symbol, depending on native number message type
!     static const t_symbol *sym_response;
! 
!     static const t_symbol *getone(t_atom &at,PyObject *arg);
!     static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0);
! 
! public:
! 
! 	static void AddToPath(const char *dir);
! 
! #ifdef FLEXT_THREADS
!     static PyThreadState *FindThreadState();
!     static void FreeThreadState();
! 
!     // this is especially needed when one py/pyext object calls another one
!     // we don't want the message to be queued, but otoh we have to avoid deadlock
!     // (recursive calls can only happen in the system thread)
!     static int lockcount;
! 
! 	static PyThreadState *PyLock(PyThreadState *st = FindThreadState()) 
!     { 
!         if(!IsSystemThread() || !lockcount++) PyEval_AcquireLock();
! 	    return PyThreadState_Swap(st);
!     }
! 
! 	static PyThreadState *PyLockSys() 
!     { 
!         if(!lockcount++) PyEval_AcquireLock();
! 	    return PyThreadState_Swap(pythrsys);
!     }
! 
! 	static void PyUnlock(PyThreadState *st) 
!     {
!         PyThreadState *old = PyThreadState_Swap(st);
!         if(old != pythrsys || !--lockcount) PyEval_ReleaseLock();
!     }
! #else
! 	static PyThreadState *PyLock(PyThreadState * = NULL) { return NULL; }
! 	static PyThreadState *PyLockSys() { return NULL; }
! 	static void PyUnlock(PyThreadState *st) {}
! #endif
! 
! 	static PyObject* StdOut_Write(PyObject* Self, PyObject* Args);
! };
! 
! #endif
--- 1,251 ----
! /* 
! 
! py/pyext - python script object for PD and MaxMSP
! 
! Copyright (c)2002-2007 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYBASE_H
! #define __PYBASE_H
! 
! #include "main.h"
! #include "pysymbol.h"
! #include "pybuffer.h"
! #include "pybundle.h"
! 
! #ifdef PY_USE_GIL
! 	typedef PyGILState_STATE ThrState;
! #else
! 	typedef PyThreadState *ThrState;
! #endif
! 
! class pybase
!     : public flext
! {
! public:
! 	pybase();
! 	virtual ~pybase();
! 
!     void Exit();
! 
! 	static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1);
! 	static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv);
! 	static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0);
! 	static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue);
! 
!     static void lib_setup();
! 
! protected:
! 
!     virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv) = 0;
! 
!     void m__dir(PyObject *obj);
! 	void m__doc(PyObject *obj);
! 
!     void m_dir() { m__dir(module); }
!     void mg_dir(AtomList &lst) { m__dir(module); }
!     void m_doc() { m__doc(dict); }
! 
!     std::string modname; // module name
! 	PyObject *module,*dict; // object module and associated dictionary
! 
! 	static const char *py_doc;
! 
!     void GetDir(PyObject *obj,AtomList &lst);
! 
! 	AtomList args;
! 
!     void AddCurrentPath(flext_base *o);
! 	void SetArgs();
! 
!     bool OutObject(flext_base *ext,int o,PyObject *obj);
! 
!     // reload module and all connected objects
!     void Reload();
! 
! 	bool ImportModule(const char *name);
! 	void UnimportModule();
! 	bool ReloadModule();
! 
!     // Get module registry
! 	PyObject *GetRegistry(const char *regname);
!     // Set module registry
! 	void SetRegistry(const char *regname,PyObject *reg);
! 
!     // Register object
! 	void Register(PyObject *reg);
!     // Unregister object
! 	void Unregister(PyObject *reg);
! 
! 	virtual void LoadModule() = 0;
! 	virtual void UnloadModule() = 0;
! 
! 	virtual void Load() = 0;
! 	virtual void Unload() = 0;
! 
!     void OpenEditor();
! 
!     void Respond(bool b)
!     { 
!         if(respond) { 
!             t_atom a; 
!             SetBool(a,b); 
!             DumpOut(sym_response,1,&a); 
!         } 
!     }
! 
!     void Report() { while(PyErr_Occurred()) PyErr_Print(); }
! 
! 	static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
! 	static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; }
! 
! //	enum retval { nothing,atom,sequ };
! 
! 	// --- module stuff -----
! 
! 	static PyObject *module_obj,*module_dict;
! 	static PyObject *builtins_obj,*builtins_dict;
! 	static PyMethodDef func_tbl[];
! 
! 	static PyObject *py__doc__(PyObject *,PyObject *args);
! 	static PyObject *py_send(PyObject *,PyObject *args);
! #ifdef FLEXT_THREADS
! 	static PyObject *py_priority(PyObject *,PyObject *args);
! #endif
! 
! 	static PyObject *py_arraysupport(PyObject *,PyObject *args);
! 	static PyObject *py_samplerate(PyObject *,PyObject *args);
! 	static PyObject *py_blocksize(PyObject *,PyObject *args);
! 
! #if FLEXT_SYS == FLEXT_SYS_PD
! 	static PyObject *py_getvalue(PyObject *,PyObject *args);
! 	static PyObject *py_setvalue(PyObject *,PyObject *args);
! #endif
! 
!     static PyObject *py_list(PyObject *,PyObject *args);
!     static PyObject *py_tuple(PyObject *,PyObject *args);
! 
! 	// ----thread stuff ------------
! 
! 	virtual void m_stop(int argc,const t_atom *argv);
! 
! 	bool respond;
! #ifdef FLEXT_THREADS
! 	int thrcount;
!     bool shouldexit;
! 	int stoptick;
!     Timer stoptmr;
! 
! 	void tick(void *);
! #endif
! 
!     int detach;
!     bool pymsg;
! 
!     bool gencall(PyObject *fun,PyObject *args);
! 
!     bool docall(PyObject *fun,PyObject *args)
!     {
!         callpy(fun,args);
!         if(PyErr_Occurred()) { 
!             exchandle(); 
!             return false; 
!         }
!         else 
!             return true;
!     }
! 
!     virtual void callpy(PyObject *fun,PyObject *args) = 0;
! 
!     void exchandle();
! 
!     static bool collect();
! 
! protected:
! 
! #ifdef FLEXT_THREADS
!     static void thrworker(thr_params *data); 
! 
!     bool qucall(PyObject *fun,PyObject *args)
!     {
!         FifoEl *el = qufifo.New();
!         el->Set(this,fun,args);
!         qufifo.Put(el);
!         qucond.Signal();
!         return true;
!     }
! 
!     static void quworker(thr_params *);
!     static void pyworker(thr_params *);
!     void erasethreads();
! 
!     static PyFifo qufifo;
!     static ThrCond qucond;
! 	
! #ifndef PY_USE_GIL
!     static ThrState pythrsys;
! #endif
! #endif
! 
!     static const t_symbol *sym_fint; // float or int symbol, depending on native number message type
!     static const t_symbol *sym_response;
! 
!     static const t_symbol *getone(t_atom &at,PyObject *arg);
!     static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0);
! 
! public:
! 
! 	static void AddToPath(const char *dir);
! 
! #ifdef FLEXT_THREADS
!     // this is especially needed when one py/pyext object calls another one
!     // we don't want the message to be queued, but otoh we have to avoid deadlock
!     // (recursive calls can only happen in the system thread)
!     static int lockcount;
! 
! #ifdef PY_USE_GIL
!     static inline ThrState FindThreadState() { return ThrState(); }
! 
! 	static inline ThrState PyLock(ThrState = ThrState()) { return PyGILState_Ensure(); }
! 	static inline ThrState PyLockSys() { return PyLock(); }
! 	static inline void PyUnlock(ThrState st) { PyGILState_Release(st); }
! #else // PY_USE_GIL
!     static ThrState FindThreadState();
!     static void FreeThreadState();
! 
! 	static ThrState PyLock(ThrState st = FindThreadState()) 
!     { 
!         if(!IsSystemThread() || !lockcount++) PyEval_AcquireLock();
! 	    return PyThreadState_Swap(st);
!     }
! 
! #if 1
! 	static inline ThrState PyLockSys() { return PyLock(); }
! #else
! 	static ThrState PyLockSys() 
!     { 
!         if(!lockcount++) PyEval_AcquireLock();
! 	    return PyThreadState_Swap(pythrsys);
!     }
! #endif
! 
! 	static void PyUnlock(ThrState st) 
!     {
!         ThrState old = PyThreadState_Swap(st);
!         if(old != pythrsys || !--lockcount) PyEval_ReleaseLock();
!     }
! #endif // PY_USE_GIL
! 	
! #else // FLEXT_THREADS
! 	static inline ThrState PyLock(ThrState = NULL) { return NULL; }
! 	static inline ThrState PyLockSys() { return NULL; }
! 	static inline void PyUnlock(ThrState st) {}
! #endif
! 
! 	static PyObject* StdOut_Write(PyObject* Self, PyObject* Args);
! };
! 
! #endif

Index: pybase.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** pybase.cpp	19 Apr 2006 17:39:41 -0000	1.17
--- pybase.cpp	7 Mar 2007 13:40:14 -0000	1.18
***************
*** 1,881 ****
! /* 
! 
! py/pyext - python external object for PD and MaxMSP
! 
! Copyright (c)2002-2006 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
[...1764 lines suppressed...]
!     // Push back
!     while(el = tmp.Get()) qufifo.Put(el);
! }
! #endif
! 
! bool pybase::collect()
! {
!     if(gcollect) {
!         PyObject *ret = PyObject_CallObject(gcollect,NULL);
!         if(ret) {
! #ifdef FLEXT_DEBUG
!             int refs = PyInt_AsLong(ret);
!             if(refs) post("py/pyext - Garbage collector reports %i unreachable objects",refs);
! #endif
!             Py_DECREF(ret);
!             return false;
!         }
!     }
!     return true;
! }

Index: py.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -d -r1.35 -r1.36
*** py.cpp	23 Mar 2006 01:42:05 -0000	1.35
--- py.cpp	7 Mar 2007 13:40:14 -0000	1.36
***************
*** 3,7 ****
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2007 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 118,122 ****
  #endif
  
! 	PyThreadState *state = PyLockSys();
  
      int inlets;
--- 118,122 ----
  #endif
  
! 	ThrState state = PyLockSys();
  
      int inlets;
***************
*** 194,198 ****
      }
      
!     PyThreadState *state = PyLockSys();
  	Unregister(GetRegistry(REGNAME));
      Report();
--- 194,198 ----
      }
      
!     ThrState state = PyLockSys();
  	Unregister(GetRegistry(REGNAME));
      Report();
***************
*** 208,212 ****
  void pyobj::m_set(int argc,const t_atom *argv)
  {
! 	PyThreadState *state = PyLockSys();
  
      // function name has precedence
--- 208,212 ----
  void pyobj::m_set(int argc,const t_atom *argv)
  {
! 	ThrState state = PyLockSys();
  
      // function name has precedence
***************
*** 242,246 ****
  {
  	post("");
! 	post("%s %s - python script object, (C)2002-2006 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
--- 242,246 ----
  {
  	post("");
! 	post("%s %s - python script object, (C)2002-2007 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
***************
*** 347,351 ****
          return flext_base::CbMethodResort(n,s,argc,argv);
  
!     PyThreadState *state = PyLockSys();
  
      bool ret = false;
--- 347,351 ----
          return flext_base::CbMethodResort(n,s,argc,argv);
  
!     ThrState state = PyLockSys();
  
      bool ret = false;

Index: pysymbol.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** pysymbol.h	26 Sep 2005 13:59:59 -0000	1.4
--- pysymbol.h	7 Mar 2007 13:40:14 -0000	1.5
***************
*** 1,54 ****
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYSYMBOL_H
! #define __PYSYMBOL_H
! 
! #include <flext.h>
! 
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500)
! #error You need at least flext version 0.5.0
! #endif
! 
! #if FLEXT_OS == FLEXT_OS_MAC
! #include <Python/Python.h>
! #else
! #include <Python.h>
! #endif
! 
! 
! #ifdef _MSC_VER
!     #ifdef PY_EXPORTS
!         #define PY_EXPORT __declspec(dllexport)
!     #else
!         #define PY_EXPORT __declspec(dllimport)
!     #endif
! #else
!     #define PY_EXPORT
! #endif
! 
! typedef struct {
!     PyObject_HEAD
!     /* Type-specific fields go here. */
!     const t_symbol *sym;
! } pySymbol;
! 
! PY_EXPORT extern PyTypeObject pySymbol_Type;
! 
! PY_EXPORT extern pySymbol *pySymbol__;
! PY_EXPORT extern pySymbol *pySymbol_bang;
! PY_EXPORT extern pySymbol *pySymbol_list;
! PY_EXPORT extern pySymbol *pySymbol_symbol;
! PY_EXPORT extern pySymbol *pySymbol_float;
! PY_EXPORT extern pySymbol *pySymbol_int;
! 
! 
  #define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type)
  #define pySymbol_CheckExact(op) ((op)->ob_type == &pySymbol_Type)
--- 1,54 ----
! /* 
! 
! py/pyext - python script object for PD and Max/MSP
! 
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
! For information on usage and redistribution, and for a DISCLAIMER OF ALL
! WARRANTIES, see the file, "license.txt," in this distribution.  
! 
! */
! 
! #ifndef __PYSYMBOL_H
! #define __PYSYMBOL_H
! 
! #include <flext.h>
! 
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500)
! #error You need at least flext version 0.5.0
! #endif
! 
! #if FLEXT_OS == FLEXT_OS_MAC
! #include <Python/Python.h>
! #else
! #include <Python.h>
! #endif
! 
! 
! #ifdef _MSC_VER
!     #ifdef PY_EXPORTS
!         #define PY_EXPORT __declspec(dllexport)
!     #else
!         #define PY_EXPORT __declspec(dllimport)
!     #endif
! #else
!     #define PY_EXPORT
! #endif
! 
! typedef struct {
!     PyObject_HEAD
!     /* Type-specific fields go here. */
!     const t_symbol *sym;
! } pySymbol;
! 
! PY_EXPORT extern PyTypeObject pySymbol_Type;
! 
! PY_EXPORT extern pySymbol *pySymbol__;
! PY_EXPORT extern pySymbol *pySymbol_bang;
! PY_EXPORT extern pySymbol *pySymbol_list;
! PY_EXPORT extern pySymbol *pySymbol_symbol;
! PY_EXPORT extern pySymbol *pySymbol_float;
! PY_EXPORT extern pySymbol *pySymbol_int;
! 
! 
  #define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type)
  #define pySymbol_CheckExact(op) ((op)->ob_type == &pySymbol_Type)
***************
*** 67,92 ****
  }
  
! inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op) 
! {
!     return ((pySymbol *)op)->sym;
! }
! 
! inline const t_symbol *pySymbol_AsSymbol(PyObject *op) 
! {
!     return pySymbol_Check(op)?pySymbol_AS_SYMBOL(op):NULL;
! }
! 
! inline const char *pySymbol_AS_STRING(PyObject *op) 
! {
!     return flext::GetString(pySymbol_AS_SYMBOL(op));
! }
! 
! inline const t_symbol *pyObject_AsSymbol(PyObject *op)
! {
!     if(PyString_Check(op))
!         return flext::MakeSymbol(PyString_AS_STRING(op));
!     else
!         return pySymbol_AsSymbol(op);
! }
! 
! #endif
--- 67,92 ----
  }
  
! inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op) 
! {
!     return ((pySymbol *)op)->sym;
! }
! 
! inline const t_symbol *pySymbol_AsSymbol(PyObject *op) 
! {
!     return pySymbol_Check(op)?pySymbol_AS_SYMBOL(op):NULL;
! }
! 
! inline const char *pySymbol_AS_STRING(PyObject *op) 
! {
!     return flext::GetString(pySymbol_AS_SYMBOL(op));
! }
! 
! inline const t_symbol *pyObject_AsSymbol(PyObject *op)
! {
!     if(PyString_Check(op))
!         return flext::MakeSymbol(PyString_AS_STRING(op));
!     else
!         return pySymbol_AsSymbol(op);
! }
! 
! #endif





More information about the Pd-cvs mailing list