From c970a0b61182435de534f39b32e8f29f5ef7b42f Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 22 Jan 2004 03:38:37 +0000 Subject: "" svn path=/trunk/; revision=1285 --- externals/grill/py/source/clmeth.cpp | 14 +++-- externals/grill/py/source/main.h | 5 +- externals/grill/py/source/modmeth.cpp | 6 +- externals/grill/py/source/py.cpp | 32 +++++++---- externals/grill/py/source/pyext.cpp | 105 ++++++++++++++++++---------------- 5 files changed, 95 insertions(+), 67 deletions(-) diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index 0c28563a..0f4ad23e 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -1,8 +1,8 @@ /* -py/pyext - python external object for PD and MaxMSP +py/pyext - python external object for PD and Max/MSP -Copyright (c) 2002-2003 Thomas Grill (xovo@gmx.net) +Copyright (c) 2002-2004 Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -40,16 +40,20 @@ PyMethodDef pyext::attr_tbl[] = const C *pyext::pyext_doc = - "py/pyext - python external object for PD and MaxMSP, (C)2002 Thomas Grill\n" + "py/pyext - python external object for PD and Max/MSP, (C)2002-2004 Thomas Grill\n" "\n" "This is the pyext base class. Available methods:\n" "_outlet(self,ix,args...): Send a message to an indexed outlet\n" +#if FLEXT_SYS == FLEXT_SYS_PD "_tocanvas(self,args...): Send a message to the parent canvas\n" -#ifdef FLEXT_THREADS - "_detach(self,int): Define whether a called Python method has its own thread\n" #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" +#ifdef FLEXT_THREADS + "_detach(self,int): Define whether a called Python method has its own thread\n" + "_stop(self): Stop running threads\n" +#endif + "_isthreaded(self): Query whether threading is enabled\n" ; PyObject* pyext::pyext__init__(PyObject *,PyObject *args) diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index b1894571..612c1c45 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -90,6 +90,8 @@ protected: V Reregister(const C *reg); virtual V Reload() = 0; + V Respond(BL b) { if(respond) { t_atom a[1]; SetBool(a[0],b); ToOutAnything(GetOutAttr(),MakeSymbol("response"),1,a); } } + static BL IsAnything(const t_symbol *s) { return s && s != sym_bang && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; } enum retval { nothing,atom,sequ /*,tuple,list*/ }; @@ -114,7 +116,7 @@ protected: virtual V m_stop(int argc,const t_atom *argv); - BL detach,shouldexit; + BL detach,shouldexit,respond; I thrcount; I stoptick; Timer stoptmr; @@ -138,6 +140,7 @@ protected: // callbacks FLEXT_ATTRVAR_B(detach) + FLEXT_ATTRVAR_B(respond) FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index b376a4fb..f7dae309 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -1,8 +1,8 @@ /* -py/pyext - python external object for PD and MaxMSP +py/pyext - python external object for PD and Max/MSP -Copyright (c) 2002-2003 Thomas Grill (xovo@gmx.net) +Copyright (c) 2002-2004 Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -28,7 +28,7 @@ PyMethodDef py::func_tbl[] = }; const C *py::py_doc = - "py/pyext - python external object for PD and MaxMSP, (C)2002 Thomas Grill\n" + "py/pyext - python external object for PD and Max/MSP, (C)2002-2004 Thomas Grill\n" "\n" "This is the pyext module. Available function:\n" "_send(args...): Send a message to a send symbol\n" diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index bfc32678..e9e7040d 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -1,8 +1,8 @@ /* -py/pyext - python script object for PD and MaxMSP +py/pyext - python script object for PD and Max/MSP -Copyright (c) 2002-2003 Thomas Grill (xovo@gmx.net) +Copyright (c) 2002-2004 Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -23,9 +23,9 @@ public: protected: BL m_method_(I n,const t_symbol *s,I argc,const t_atom *argv); - V work(const t_symbol *s,I argc,const t_atom *argv); + BL work(const t_symbol *s,I argc,const t_atom *argv); - V m_bang() { work(sym_bang,0,NULL); } + V m_bang() { callwork(sym_bang,0,NULL); } V m_reload(); V m_reload_(I argc,const t_atom *argv); V m_set(I argc,const t_atom *argv); @@ -94,6 +94,8 @@ void pyobj::Setup(t_classid c) FLEXT_CADDMETHOD_(c,1,"int",m_py_int); FLEXT_CADDMETHOD(c,1,m_py_list); FLEXT_CADDMETHOD(c,1,m_py_any); + + FLEXT_CADDATTR_VAR1(c,"respond",respond); } pyobj::pyobj(I argc,const t_atom *argv): @@ -227,6 +229,8 @@ V pyobj::m_help() 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: detach threads"); post("\tstop {wait time (ms)}: stop threads"); @@ -271,9 +275,10 @@ V pyobj::Reload() } -V pyobj::work(const t_symbol *s,I argc,const t_atom *argv) +BL pyobj::work(const t_symbol *s,I argc,const t_atom *argv) { AtomList *rargs = NULL; + BL ret; ++thrcount; PY_LOCK @@ -287,9 +292,11 @@ V pyobj::work(const t_symbol *s,I argc,const t_atom *argv) Py_XDECREF(pArgs); Py_XDECREF(pValue); + ret = true; } else { post("%s: no function defined",thisName()); + ret = false; } PY_UNLOCK @@ -301,19 +308,24 @@ V pyobj::work(const t_symbol *s,I argc,const t_atom *argv) ToOutList(0,*rargs); delete rargs; } + + return ret; } V pyobj::callwork(const t_symbol *s,I argc,const t_atom *argv) { + BL ret = false; if(detach) { if(shouldexit) post("%s - New threads can't be launched now!",thisName()); - else - if(!FLEXT_CALLMETHOD_A(work,s,argc,argv)) - post("%s - Failed to launch thread!",thisName()); + else { + ret = FLEXT_CALLMETHOD_A(work,s,argc,argv); + if(!ret) post("%s - Failed to launch thread!",thisName()); + } } - else - work(s,argc,argv); + else + ret = work(s,argc,argv); + Respond(ret); } diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index 924a6fec..7dd4d805 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -1,6 +1,6 @@ /* -py/pyext - python script object for PD and MaxMSP +py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2004 Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL @@ -32,6 +32,8 @@ V pyext::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"get",m_get); FLEXT_CADDMETHOD_(c,0,"set",m_set); + + FLEXT_CADDATTR_VAR1(c,"respond",respond); } pyext *pyext::GetThis(PyObject *self) @@ -224,7 +226,6 @@ pyext::~pyext() Unregister("_pyext"); Py_XDECREF(pyobj); - Py_XDECREF(class_obj); Py_XDECREF(class_dict); @@ -244,39 +245,45 @@ BL pyext::SetClssMeth() //I argc,t_atom *argv) PyObject *pref = PyObject_GetAttrString(module,const_cast(GetString(methname))); if(!pref) PyErr_Print(); - else if(PyClass_Check(pref)) { - // make instance, but don't call __init__ - pyobj = PyInstance_NewRaw(pref,NULL); + else { + if(PyClass_Check(pref)) { + // make instance, but don't call __init__ + pyobj = PyInstance_NewRaw(pref,NULL); + + Py_DECREF(pref); + if(pyobj == NULL) + PyErr_Print(); + else { + // remember the this pointer + PyObject *th = PyLong_FromVoidPtr(this); + int ret = PyObject_SetAttrString(pyobj,"_this",th); // ref is taken + + // call init now, after _this has been set, which is + // important for eventual callbacks from __init__ to c + PyObject *pargs = MakePyArgs(NULL,args,-1,true); + if (pargs == NULL) PyErr_Print(); + + PyObject *init; + init = PyObject_GetAttrString(pyobj,"__init__"); // get ref + if(init) { + if(PyCallable_Check(init)) { + PyObject *res = PyEval_CallObject(init,pargs); + if(!res) + PyErr_Print(); + else + Py_DECREF(res); + } + Py_DECREF(init); + } + + Py_XDECREF(pargs); + } + } + else + post("%s - Type of \"%s\" is unhandled!",thisName(),GetString(methname)); - Py_DECREF(pref); - if(pyobj == NULL) - PyErr_Print(); - else { - // remember the this pointer - PyObject *th = PyLong_FromVoidPtr(this); - int ret = PyObject_SetAttrString(pyobj,"_this",th); // ref is taken - - // call init now, after _this has been set, which is - // important for eventual callbacks from __init__ to c - PyObject *pargs = MakePyArgs(NULL,args,-1,true); - if (pargs == NULL) PyErr_Print(); - - PyObject *init; - init = PyObject_GetAttrString(pyobj,"__init__"); // get ref - if(init && PyCallable_Check(init)) { - PyObject *res = PyEval_CallObject(init,pargs); - if(!res) - PyErr_Print(); - else - Py_DECREF(res); - Py_DECREF(init); - } - - Py_XDECREF(pargs); - } + Py_DECREF(pref); } - else - post("%s - Type of \"%s\" is unhandled!",thisName(),GetString(methname)); return true; } else @@ -287,6 +294,7 @@ V pyext::Reload() { ClearBinding(); Py_XDECREF(pyobj); + // by here, the Python class destructor should have been called! SetArgs(0,NULL); @@ -321,7 +329,7 @@ void pyext::m_get(const t_symbol *s) PY_LOCK PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast(GetString(s))); /* fetch bound method */ - if(pvar == NULL) { + if(!pvar) { PyErr_Clear(); // no method found post("%s - get: Python variable %s not found",thisName(),GetString(s)); } @@ -384,13 +392,12 @@ void pyext::m_set(int argc,const t_atom *argv) BL pyext::m_method_(I n,const t_symbol *s,I argc,const t_atom *argv) { - if(pyobj && n >= 1) { - return callwork(n,s,argc,argv); - } - else { + BL ret = false; + if(pyobj && n >= 1) + ret = callwork(n,s,argc,argv); + else post("%s - no method for type '%s' into inlet %i",thisName(),GetString(s),n); - return false; - } + return ret; } @@ -413,6 +420,8 @@ V pyext::m_help() post("\treload. : reload with former arguments"); post("\tdoc: display module doc string"); post("\tdoc+: display class doc string"); + post("\tdir: dump module dictionary"); + post("\tdir+: dump class dictionary"); #ifdef FLEXT_THREADS post("\tdetach 0/1: detach threads"); post("\tstop {wait time (ms)}: stop threads"); @@ -502,19 +511,19 @@ V pyext::work_wrapper(V *data) BL pyext::callwork(I n,const t_symbol *s,I argc,const t_atom *argv) { - if(detach) { - if(shouldexit) { + BL ret = true,ok = false; + if(detach) { + if(shouldexit) post("%s - Stopping.... new threads can't be launched now!",thisName()); - return true; - } else { - BL ret = FLEXT_CALLMETHOD_X(work_wrapper,new work_data(n,s,argc,argv)); + ret = FLEXT_CALLMETHOD_X(work_wrapper,new work_data(n,s,argc,argv)); if(!ret) post("%s - Failed to launch thread!",thisName()); - return true; } } - else - return work(n,s,argc,argv); + else + ret = ok = work(n,s,argc,argv); + Respond(ok); + return ret; } BL pyext::work(I n,const t_symbol *s,I argc,const t_atom *argv) -- cgit v1.2.1