diff options
-rw-r--r-- | externals/grill/py/readme.txt | 5 | ||||
-rw-r--r-- | externals/grill/py/source/bound.cpp | 18 | ||||
-rw-r--r-- | externals/grill/py/source/clmeth.cpp | 105 | ||||
-rw-r--r-- | externals/grill/py/source/pybase.cpp | 3 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.h | 4 |
5 files changed, 93 insertions, 42 deletions
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt index 7c782c82..34be0a14 100644 --- a/externals/grill/py/readme.txt +++ b/externals/grill/py/readme.txt @@ -102,6 +102,11 @@ Version history: - FIX: much better detached method handling (one thread for all object instances!) - ADD: open module file in editor on "edit" message (or shift-click (PD) or double click (Max)) - FIX: _inlets and _outlets default to 0 if not given +- ADD: enable optimization of Python code in reease build +- CHG: _isthreaded is now a data member instead of a method +- FIX: more safety for calls where association python-pd has already been removed +- ADD: __str__ method for pyext, to enable print self calls +- CHG: enable symbol binding for all callables (not only functions and methods) 0.2.0: - ADD: handling of Python threads diff --git a/externals/grill/py/source/bound.cpp b/externals/grill/py/source/bound.cpp index 4c57f65f..3e7bc386 100644 --- a/externals/grill/py/source/bound.cpp +++ b/externals/grill/py/source/bound.cpp @@ -46,7 +46,7 @@ public: if(PyMethod_Check(b)) return true; else - // both are functions + // both are non-method callables return a < b; } }; @@ -88,12 +88,15 @@ PyObject *pyext::pyext_bind(PyObject *,PyObject *args) PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); - else if(!PyInstance_Check(self) || !(PyMethod_Check(meth) || PyFunction_Check(meth))) { + else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { pyext *th = GetThis(self); - FLEXT_ASSERT(th); + if(!th) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _bind: instance not associated with pd object"); + return NULL; + } const t_symbol *recv = pyObject_AsSymbol(name); @@ -130,12 +133,15 @@ PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); - else if(!PyInstance_Check(self) || !(PyMethod_Check(meth) || PyFunction_Check(meth))) { + else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { pyext *th = GetThis(self); - FLEXT_ASSERT(th); + if(!th) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _unbind: instance not associated with pd object"); + return NULL; + } const t_symbol *recv = pyObject_AsSymbol(name); @@ -175,7 +181,7 @@ void pyext::ClearBinding() if(!pyobj) return; pyext *th = GetThis(pyobj); - FLEXT_ASSERT(th); + if(!th) return; void *data = NULL; const t_symbol *sym = NULL; diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index 30474eff..c8d38f81 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -17,6 +17,7 @@ PyMethodDef pyext::meth_tbl[] = {"__init__", pyext::pyext__init__, METH_VARARGS, "Constructor"}, {"__del__", pyext::pyext__del__, METH_VARARGS, "Destructor"}, */ + {"__str__", pyext::pyext__str__, METH_VARARGS, "stringify"}, {"_outlet", pyext::pyext_outlet, METH_VARARGS,"Send message to outlet"}, #if FLEXT_SYS == FLEXT_SYS_PD {"_tocanvas", pyext::pyext_tocanvas, METH_VARARGS,"Send message to canvas" }, @@ -28,8 +29,6 @@ PyMethodDef pyext::meth_tbl[] = { "_detach", pyext::pyext_detach, METH_VARARGS,"Set detach flag for called methods" }, { "_stop", pyext::pyext_stop, METH_VARARGS,"Stop running threads" }, #endif - { "_isthreaded", pyext::pyext_isthreaded, METH_O,"Query whether threading is enabled" }, - { "_invec", pyext::pyext_invec, METH_VARARGS,"Get input vector" }, { "_outvec", pyext::pyext_outvec, METH_VARARGS,"Get output vector" }, {NULL, NULL, 0, NULL} /* Sentinel */ @@ -53,11 +52,12 @@ const char *pyext::pyext_doc = #endif "_bind(self,name,func): Bind a python function to a symbol\n" "_unbind(self,name,func): Unbind a python function from a symbol\n" + "_isthreaded: Query whether threading is enabled\n" #ifdef FLEXT_THREADS "_detach(self,int): Define whether a called Python method has its own thread\n" "_stop(self): Stop running threads\n" + "_shouldexit: Query whether threads should terminate\n" #endif - "_isthreaded(self): Query whether threading is enabled\n" ; /* @@ -78,10 +78,22 @@ PyObject* pyext::pyext__del__(PyObject *,PyObject *args) } */ +PyObject* pyext::pyext__str__(PyObject *,PyObject *args) +{ + PyObject *self; + if(!PyArg_ParseTuple(args, "O:pyext__str__",&self)) { + // handle error + ERRINTERNAL(); + return NULL; + } + + return PyString_FromFormat("<pyext object %p>",self); +} + PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) { PyObject *self,*name,*val; - if(!PyArg_ParseTuple(args, "OOO:test_foo", &self,&name,&val)) { + if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) { // handle error ERRINTERNAL(); return NULL; @@ -111,28 +123,38 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) { PyObject *self,*name,*ret = NULL; - if(!PyArg_ParseTuple(args, "OO:test_foo", &self,&name)) { + if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self,&name)) { // handle error ERRINTERNAL(); } -#ifdef FLEXT_THREADS if(PyString_Check(name)) { char* sname = PyString_AS_STRING(name); if(sname) { +#ifdef FLEXT_THREADS if(!strcmp(sname,"_shouldexit")) { pyext *ext = GetThis(self); if(ext) ret = PyLong_FromLong(ext->shouldexit?1:0); else { + // return true for _shouldexit if association has been removed Py_INCREF(Py_True); ret = Py_True; } } -// post("pyext::getattr %s",sname); + else +#endif + if(!strcmp(sname,"_isthreaded")) { + #ifdef FLEXT_THREADS + Py_INCREF(Py_True); + ret = Py_True; + #else + Py_INCREF(Py_False); + ret = Py_False; + #endif + } } } -#endif if(!ret) { #if PY_VERSION_HEX >= 0x02020000 @@ -165,7 +187,10 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ) { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); + if(!ext) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _outlet: instance not associated with pd object"); + return NULL; + } PyObject *val; #if 0 @@ -230,7 +255,11 @@ PyObject *pyext::pyext_detach(PyObject *,PyObject *args) } else { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); + if(!ext) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _detach: instance not associated with pd object"); + return NULL; + } + ext->detach = val; } @@ -254,7 +283,11 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) } else { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); + if(!ext) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _stop: instance not associated with pd object"); + return NULL; + } + int cnt; t_atom at; if(val >= 0) cnt = 1,flext::SetInt(at,val); @@ -268,17 +301,6 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) #endif -//! Query whether threading is enabled -PyObject *pyext::pyext_isthreaded(PyObject *,PyObject *) -{ - return PyInt_FromLong( -#ifdef FLEXT_THREADED - 1 -#else - 0 -#endif - ); -} #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas @@ -295,7 +317,11 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) ) { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); + if(!ext) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _tocanvas: instance not associated with pd object"); + return NULL; + } + PyObject *val; bool tp = @@ -310,10 +336,13 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) flext::AtomListStatic<16> lst; const t_symbol *sym = GetPyArgs(lst,val); if(sym) { - t_glist *gl = ext->thisCanvas(); //canvas_getcurrent(); - t_class **cl = (t_pd *)gl; - if(cl) - pd_forwardmess(cl,lst.Count(),lst.Atoms()); + t_glist *gl = ext->thisCanvas(); + if(gl) { + // \TODO find a flext-based non-locking method + sys_lock(); + pd_forwardmess((t_class **)gl,lst.Count(),lst.Atoms()); + sys_unlock(); + } #ifdef FLEXT_DEBUG else post("pyext - no parent canvas?!"); @@ -351,9 +380,14 @@ PyObject *pyext::pyext_invec(PyObject *,PyObject *args) } else { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); - PyObject *b = ext->GetSig(val,true); - if(b) return b; + if(ext) { + PyObject *b = ext->GetSig(val,true); + if(b) return b; + } + else { + PyErr_SetString(PyExc_RuntimeError,"pyext - _invec: instance not associated with pd object"); + return NULL; + } } Py_INCREF(Py_None); @@ -375,9 +409,14 @@ PyObject *pyext::pyext_outvec(PyObject *,PyObject *args) } else { pyext *ext = GetThis(self); - FLEXT_ASSERT(ext); - PyObject *b = ext->GetSig(val,false); - if(b) return b; + if(ext) { + PyObject *b = ext->GetSig(val,false); + if(b) return b; + } + else { + PyErr_SetString(PyExc_RuntimeError,"pyext - _outvec: instance not associated with pd object"); + return NULL; + } } Py_INCREF(Py_None); diff --git a/externals/grill/py/source/pybase.cpp b/externals/grill/py/source/pybase.cpp index b7a112e9..09fd8687 100644 --- a/externals/grill/py/source/pybase.cpp +++ b/externals/grill/py/source/pybase.cpp @@ -101,7 +101,10 @@ void pybase::lib_setup() Py_Initialize();
#ifdef FLEXT_DEBUG
+ Py_DebugFlag = 1;
// Py_VerboseFlag = 1;
+#else
+ Py_OptimizeFlag = 1;
#endif
#ifdef FLEXT_THREADS
diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h index 4a4e79f1..672fe5f1 100644 --- a/externals/grill/py/source/pyext.h +++ b/externals/grill/py/source/pyext.h @@ -22,9 +22,7 @@ class pyext public: pyext(int argc,const t_atom *argv,bool sig = false); - static PyObject *pyext__doc__(PyObject *,PyObject *args); - static PyObject *pyext__init__(PyObject *,PyObject *args); - static PyObject *pyext__del__(PyObject *,PyObject *args); + static PyObject *pyext__str__(PyObject *,PyObject *args); static PyObject *pyext_outlet(PyObject *,PyObject *args); #if FLEXT_SYS == FLEXT_SYS_PD |