diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-31 03:54:11 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-31 03:54:11 +0000 |
commit | 64d57eae96b65b3d618d8b3e8d68111da80f283a (patch) | |
tree | 886f24cf54d210509fa85ebd8c5dfbd3864a9bdb /externals | |
parent | 6c94eab605e5ec018654541bf2bf410b7db17788 (diff) |
fixed reference count bug
cleaner error reporting
more optimizations
added generic numpy support (not working)
fixes for maxmsp
svn path=/trunk/; revision=2655
Diffstat (limited to 'externals')
-rw-r--r-- | externals/grill/py/pd/script-1.pd | 4 | ||||
-rw-r--r-- | externals/grill/py/source/clmeth.cpp | 25 | ||||
-rw-r--r-- | externals/grill/py/source/main.cpp | 33 | ||||
-rw-r--r-- | externals/grill/py/source/main.h | 14 | ||||
-rw-r--r-- | externals/grill/py/source/modmeth.cpp | 21 | ||||
-rw-r--r-- | externals/grill/py/source/py.cpp | 170 | ||||
-rw-r--r-- | externals/grill/py/source/pyargs.cpp | 34 | ||||
-rw-r--r-- | externals/grill/py/source/pybuffer.cpp | 12 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.cpp | 137 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.h | 16 |
10 files changed, 234 insertions, 232 deletions
diff --git a/externals/grill/py/pd/script-1.pd b/externals/grill/py/pd/script-1.pd index 27b63d43..328b096d 100644 --- a/externals/grill/py/pd/script-1.pd +++ b/externals/grill/py/pd/script-1.pd @@ -1,4 +1,4 @@ -#N canvas 297 17 692 534 12;
+#N canvas 297 17 696 538 12;
#X obj 39 278 print;
#X obj 345 251 print;
#X msg 499 149 freakhole;
@@ -38,6 +38,7 @@ file.; #X msg 509 178 a b c;
#X text 556 181 too many args;
#X text 505 372 just trigger without arguments;
+#X msg 386 371 set ret4;
#X connect 2 0 25 1;
#X connect 3 0 21 1;
#X connect 4 0 21 1;
@@ -60,3 +61,4 @@ file.; #X connect 26 0 21 0;
#X connect 28 0 21 0;
#X connect 32 0 25 1;
+#X connect 35 0 23 0;
diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index cfd8604a..4b403cf8 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -173,8 +173,8 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) if(!tp) val = PySequence_GetSlice(args,2,sz); // new ref - AtomList *lst = GetPyArgs(val); - if(lst) { + AtomListStatic<16> lst; + if(GetPyArgs(lst,val)) { int o = PyInt_AsLong(outl); if(o >= 1 && o <= ext->Outlets()) { // offset outlet by signal outlets @@ -182,12 +182,12 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) // by using the queue there is no immediate call of the next object // deadlock would occur if this was another py/pyext object! - if(lst->Count() && IsSymbol((*lst)[0])) - ext->ToOutAnything(o-1,GetSymbol((*lst)[0]),lst->Count()-1,lst->Atoms()+1); - else if(lst->Count() > 1) - ext->ToOutList(o-1,*lst); + if(lst.Count() && IsSymbol(lst[0])) + ext->ToOutAnything(o-1,GetSymbol(lst[0]),lst.Count()-1,lst.Atoms()+1); + else if(lst.Count() > 1) + ext->ToOutList(o-1,lst); else - ext->ToOutAtom(o-1,*lst->Atoms()); + ext->ToOutAtom(o-1,*lst.Atoms()); } else post("pyext: outlet index out of range"); @@ -196,7 +196,6 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) } else post("py/pyext - No data to send"); - if(lst) delete lst; if(!tp) Py_DECREF(val); } @@ -296,13 +295,12 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) if(!tp) val = PyTuple_GetSlice(args,1,sz); // new ref - AtomList *lst = GetPyArgs(val); - if(lst) { + AtomListStatic<16> lst; + if(GetPyArgs(lst,val)) { t_glist *gl = ext->thisCanvas(); //canvas_getcurrent(); t_class **cl = (t_pd *)gl; - if(cl) { - pd_forwardmess(cl,lst->Count(),lst->Atoms()); - } + if(cl) + pd_forwardmess(cl,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG else post("pyext - no parent canvas?!"); @@ -311,7 +309,6 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) } else post("py/pyext - No data to send"); - if(lst) delete lst; if(!tp) Py_DECREF(val); } diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp index 3b0aa869..608ecdd7 100644 --- a/externals/grill/py/source/main.cpp +++ b/externals/grill/py/source/main.cpp @@ -205,11 +205,7 @@ void pybase::GetDir(PyObject *obj,AtomList &lst) if(!pvar) PyErr_Print(); // no method found else { - AtomList *l = GetPyArgs(pvar); - if(l) { - lst = *l; delete l; - } - else + if(!GetPyArgs(lst,pvar)) post("py/pyext - Argument list could not be created"); Py_DECREF(pvar); } @@ -267,9 +263,11 @@ void pybase::OpenEditor() // this should once open the editor.... } -void pybase::SetArgs(int argc,const t_atom *argv) +void pybase::SetArgs() { // script arguments + int argc = args.Count(); + const t_atom *argv = args.Atoms(); char **sargv = new char *[argc+1]; for(int i = 0; i <= argc; ++i) { sargv[i] = new char[256]; @@ -286,17 +284,15 @@ void pybase::SetArgs(int argc,const t_atom *argv) delete[] sargv; } -void pybase::ImportModule(const char *name) +bool pybase::ImportModule(const char *name) { - if(!name) return; + if(!name) return false; + SetArgs(); module = PyImport_ImportModule((char *)name); // increases module_obj ref count by one - if(!module) { - PyErr_Print(); - dict = NULL; - } - else - dict = PyModule_GetDict(module); + dict = module?PyModule_GetDict(module):NULL; + + return module != NULL; } void pybase::UnimportModule() @@ -315,12 +311,13 @@ void pybase::UnimportModule() dict = NULL; } -void pybase::ReloadModule() +bool pybase::ReloadModule() { + bool ok = false; if(module) { + SetArgs(); PyObject *newmod = PyImport_ReloadModule(module); if(!newmod) { - PyErr_Print(); // old module still exists?! // dict = NULL; } @@ -328,10 +325,12 @@ void pybase::ReloadModule() Py_XDECREF(module); module = newmod; dict = PyModule_GetDict(module); // borrowed + ok = true; } } - else + else post("py/pyext - No module to reload"); + return ok; } void pybase::GetModulePath(const char *mod,char *dir,int len) diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index f9df5807..538e577d 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -52,7 +52,7 @@ public: void Exit(); static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1,bool withself = false); - static AtomList *GetPyArgs(PyObject *pValue,PyObject **self = NULL); + static bool GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0,PyObject **self = NULL); static void lib_setup(); @@ -73,21 +73,25 @@ protected: void GetDir(PyObject *obj,AtomList &lst); + AtomListStatic<16> args; + void GetModulePath(const char *mod,char *dir,int len); void AddToPath(const char *dir); - void SetArgs(int argc,const t_atom *argv); - void ImportModule(const char *name); + void SetArgs(); + bool ImportModule(const char *name); void UnimportModule(); - void ReloadModule(); + bool ReloadModule(); void Register(const char *reg); void Unregister(const char *reg); void Reregister(const char *reg); - virtual void Reload() = 0; + virtual bool Reload() = 0; void OpenEditor(); void Respond(bool b); + 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; } enum retval { nothing,atom,sequ }; diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index bbbe64b1..983176bf 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -126,22 +126,23 @@ PyObject *pybase::py_send(PyObject *,PyObject *args) if(!tp) val = PySequence_GetSlice(args,1,sz); // new ref - AtomList *lst = GetPyArgs(val); - if(lst) { + AtomListStatic<16> lst; + if(GetPyArgs(lst,val)) { bool ok; - if(lst->Count() && IsSymbol((*lst)[0])) - ok = Forward(recv,GetSymbol((*lst)[0]),lst->Count()-1,lst->Atoms()+1); + if(lst.Count() && IsSymbol(lst[0])) + ok = Forward(recv,GetSymbol(lst[0]),lst.Count()-1,lst.Atoms()+1); else - ok = Forward(recv,*lst); + ok = Forward(recv,lst); #ifdef FLEXT_DEBUG if(!ok) post("py/pyext - Receiver doesn't exist"); #endif } - else + else if(PyErr_Occurred()) + PyErr_Print(); + else post("py/pyext - No data to send"); - if(lst) delete lst; if(!tp) Py_DECREF(val); } @@ -183,14 +184,16 @@ PyObject *pybase::py_getvalue(PyObject *self,PyObject *args) float f; if(value_getfloat(const_cast<t_symbol *>(sym),&f)) { post("py/pyext - Could not get value '%s'",GetString(sym)); - Py_INCREF(ret = Py_None); + Py_INCREF(Py_None); + ret = Py_None; } else ret = PyFloat_FromDouble(f); } else { post("py/pyext - Syntax: _getvalue [name]"); - Py_INCREF(ret = Py_None); + Py_INCREF(Py_None); + ret = Py_None; } return ret; } diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index eb1d2390..4f46a9ea 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -30,7 +30,7 @@ protected: void m_help(); void m_reload(); - void m_reload_(int argc,const t_atom *argv); + void m_reload_(int argc,const t_atom *argv) { args(argc,argv); m_reload(); } void m_set(int argc,const t_atom *argv); void m_dir_() { m__dir(function); } void m_doc_() { m__doc(function); } @@ -48,10 +48,10 @@ protected: PyObject *function; bool withfunction; - virtual void Reload(); + virtual bool Reload(); - void SetFunction(const char *func); - void ResetFunction(); + bool SetFunction(const char *func); + bool ResetFunction(); virtual bool thrcall(void *data); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); @@ -133,20 +133,16 @@ pyobj::pyobj(int argc,const t_atom *argv): FLEXT_CALLMETHOD(threadworker); #endif - PyThreadState *state = PyLockSys(); + if(argc > 2) args(argc-2,argv+2); - if(argc > 2) - SetArgs(argc-2,argv+2); - else - SetArgs(0,NULL); + PyThreadState *state = PyLockSys(); // init script module if(argc >= 1) { - if(!IsString(argv[0])) - post("%s - script name argument is invalid",thisName()); - else { + const char *sn = GetAString(argv[0]); + if(sn) { char dir[1024]; - GetModulePath(GetString(argv[0]),dir,sizeof(dir)); + GetModulePath(sn,dir,sizeof(dir)); // set script path AddToPath(dir); @@ -163,25 +159,23 @@ pyobj::pyobj(int argc,const t_atom *argv): #pragma message("Adding current dir to path is not implemented") #endif - ImportModule(GetString(argv[0])); + ImportModule(sn); } + else + PyErr_SetString(PyExc_ValueError,"Invalid module name"); } Register("_py"); - if(argc >= 2) { - withfunction = true; - - // set function name - if(!IsString(argv[1])) - post("%s - function name argument is invalid",thisName()); - else { - // Set function - SetFunction(GetString(argv[1])); - } - } - else - withfunction = false; + if(argc >= 2) { + const char *fn = GetAString(argv[1]); + if(fn) + SetFunction(fn); + else + PyErr_SetString(PyExc_ValueError,"Invalid function name"); + } + + Report(); PyUnlock(state); } @@ -190,6 +184,7 @@ pyobj::~pyobj() { PyThreadState *state = PyLockSys(); Unregister("_py"); + Report(); PyUnlock(state); } @@ -217,42 +212,38 @@ void pyobj::m_reload() Register("_py"); SetFunction(funname?GetString(funname):NULL); + Report(); PyUnlock(state); } -void pyobj::m_reload_(int argc,const t_atom *argv) -{ - PyThreadState *state = PyLockSys(); - SetArgs(argc,argv); - PyUnlock(state); - - m_reload(); -} - void pyobj::m_set(int argc,const t_atom *argv) { PyThreadState *state = PyLockSys(); - int ix = 0; + // function name has precedence if(argc >= 2) { - if(!IsString(argv[ix])) { - post("%s - script name is not valid",thisName()); - return; - } - const char *sn = GetString(argv[ix]); - - if(!module || !strcmp(sn,PyModule_GetName(module))) { - ImportModule(sn); - Register("_py"); - } - - ++ix; + const char *sn = GetAString(*argv); + ++argv,--argc; + + if(sn) { + if(!module || !strcmp(sn,PyModule_GetName(module))) { + ImportModule(sn); + Register("_py"); + } + } + else + PyErr_SetString(PyExc_ValueError,"Invalid module name"); } - if(!IsString(argv[ix])) - post("%s - function name is not valid",thisName()); - else - SetFunction(GetString(argv[ix])); + if(argc) { + const char *fn = GetAString(*argv); + if(fn) + SetFunction(fn); + else + PyErr_SetString(PyExc_ValueError,"Invalid function name"); + } + + Report(); PyUnlock(state); } @@ -287,43 +278,48 @@ void pyobj::m_help() post(""); } -void pyobj::ResetFunction() +bool pyobj::ResetFunction() { - if(!module || !dict) - { + function = NULL; + + if(!module || !dict) post("%s - No module loaded",thisName()); - function = NULL; - return; - } + else { + if(funname) { + function = PyDict_GetItemString(dict,(char *)GetString(funname)); // borrowed!!! + if(!function) + PyErr_SetString(PyExc_AttributeError,"Function not found"); + else if(!PyFunction_Check(function)) { + function = NULL; + PyErr_SetString(PyExc_TypeError,"Attribute is not a function"); + } + } + } - function = funname?PyDict_GetItemString(dict,(char *)GetString(funname)):NULL; // borrowed!!! - if(!function) { - PyErr_Clear(); - if(funname) post("%s - Function %s could not be found",thisName(),GetString(funname)); - } - else if(!PyFunction_Check(function)) { - post("%s - Object %s is not a function",thisName(),GetString(funname)); - function = NULL; - } + // exception could be set here + return function != NULL; } -void pyobj::SetFunction(const char *func) +bool pyobj::SetFunction(const char *func) { if(func) { funname = MakeSymbol(func); - withfunction = true; - ResetFunction(); + withfunction = ResetFunction(); } else { - withfunction = false; function = NULL,funname = NULL; + withfunction = false; } + + // exception could be set here + return withfunction; } -void pyobj::Reload() +bool pyobj::Reload() { ResetFunction(); + return true; } bool pyobj::callpy(PyObject *fun,PyObject *args) @@ -335,15 +331,15 @@ bool pyobj::callpy(PyObject *fun,PyObject *args) return false; } else { - AtomList *rargs = GetPyArgs(ret); - if(!rargs) - PyErr_Print(); - else { + AtomListStatic<16> rargs; + if(GetPyArgs(rargs,ret)) { // call to outlet _outside_ the Mutex lock! // otherwise (if not detached) deadlock will occur - if(rargs->Count()) ToOutList(0,*rargs); - delete rargs; + if(rargs.Count()) ToOutList(0,rargs); } + else if(PyErr_Occurred()) + PyErr_Print(); + Py_DECREF(ret); return true; } @@ -362,19 +358,23 @@ void pyobj::callwork(const t_symbol *s,int argc,const t_atom *argv) ret = gencall(function,pargs); } else - post("%s: no valid function defined",thisName()); + PyErr_SetString(PyExc_RuntimeError,"No function set"); } else if(module) { // no function defined as creation argument -> use message tag - PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); - if(func) { - PyObject *pargs = MakePyArgs(sym_list,argc,argv); - ret = gencall(func,pargs); + if(s) { + PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); + if(func) { + PyObject *pargs = MakePyArgs(sym_list,argc,argv); + ret = gencall(func,pargs); + } } else - PyErr_Print(); + PyErr_SetString(PyExc_RuntimeError,"No function set"); } + Report(); + PyUnlock(state); Respond(ret); diff --git a/externals/grill/py/source/pyargs.cpp b/externals/grill/py/source/pyargs.cpp index 56b0123a..5e328975 100644 --- a/externals/grill/py/source/pyargs.cpp +++ b/externals/grill/py/source/pyargs.cpp @@ -84,10 +84,9 @@ PyObject *pybase::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int i return pArgs; } -flext::AtomList *pybase::GetPyArgs(PyObject *pValue,PyObject **self) +bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs,PyObject **self) { - if(pValue == NULL) return NULL; - AtomList *ret = NULL; + if(pValue == NULL) return false; // analyze return value or tuple @@ -103,14 +102,14 @@ flext::AtomList *pybase::GetPyArgs(PyObject *pValue,PyObject **self) rargc = PySequence_Size(pValue); tp = sequ; } - else if(pValue == Py_None) - Py_DECREF(pValue); - else { + else if(pValue != Py_None) { rargc = 1; tp = atom; } +// else +// Py_DECREF(pValue); - ret = new AtomList(rargc); + lst(offs+rargc); for(int ix = 0; ix < rargc; ++ix) { PyObject *arg; @@ -119,11 +118,12 @@ flext::AtomList *pybase::GetPyArgs(PyObject *pValue,PyObject **self) else arg = pValue; - if(PyInt_Check(arg)) SetInt((*ret)[ix],PyInt_AsLong(arg)); - else if(PyLong_Check(arg)) SetInt((*ret)[ix],PyLong_AsLong(arg)); - else if(PyFloat_Check(arg)) SetFloat((*ret)[ix],(float)PyFloat_AsDouble(arg)); - else if(pySymbol_Check(arg)) SetSymbol((*ret)[ix],pySymbol_AS_SYMBOL(arg)); - else if(PyString_Check(arg)) SetString((*ret)[ix],PyString_AS_STRING(arg)); + t_atom &at = lst[offs+ix]; + if(PyInt_Check(arg)) SetInt(at,PyInt_AsLong(arg)); + else if(PyLong_Check(arg)) SetInt(at,PyLong_AsLong(arg)); + else if(PyFloat_Check(arg)) SetFloat(at,(float)PyFloat_AsDouble(arg)); + else if(pySymbol_Check(arg)) SetSymbol(at,pySymbol_AS_SYMBOL(arg)); + else if(PyString_Check(arg)) SetString(at,PyString_AS_STRING(arg)); else if(ix == 0 && self && PyInstance_Check(arg)) { // assumed to be self ... that should be checked _somehow_ !!! Py_INCREF(arg); @@ -140,13 +140,9 @@ flext::AtomList *pybase::GetPyArgs(PyObject *pValue,PyObject **self) ok = false; } - if(tp == sequ) Py_DECREF(arg); + if(tp == sequ) + Py_DECREF(arg); } - if(!ok) { - delete ret; - ret = NULL; - } - return ret; + return ok; } - diff --git a/externals/grill/py/source/pybuffer.cpp b/externals/grill/py/source/pybuffer.cpp index 8f22acf1..42e23557 100644 --- a/externals/grill/py/source/pybuffer.cpp +++ b/externals/grill/py/source/pybuffer.cpp @@ -217,8 +217,10 @@ static PyObject *buffer_item(pySamplebuffer *self, int i) }
}
}
- else
- Py_INCREF(ret = Py_None);
+ else {
+ Py_INCREF(Py_None);
+ ret = Py_None;
+ }
return ret;
}
@@ -274,8 +276,10 @@ static PyObject *buffer_slice(pySamplebuffer *self,int ilow = 0,int ihigh = 1<<( else
ret = nobj;
}
- else
- Py_INCREF(ret = Py_None);
+ else {
+ Py_INCREF(Py_None);
+ ret = Py_None;
+ }
}
else
#endif
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index 2d772d15..7d234956 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -35,7 +35,7 @@ void pyext::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_); FLEXT_CADDATTR_GET(c,"dir+",mg_dir_); - FLEXT_CADDATTR_VAR(c,"args",args,ms_args); + FLEXT_CADDATTR_VAR(c,"args",initargs,ms_initargs); FLEXT_CADDMETHOD_(c,0,"get",m_get); FLEXT_CADDMETHOD_(c,0,"set",m_set); @@ -129,7 +129,7 @@ pyext::pyext(int argc,const t_atom *argv,bool sig): apre += 2; } - const t_atom *clname = NULL; + const t_symbol *clname = NULL; PyThreadState *state = PyLockSys(); @@ -149,39 +149,40 @@ pyext::pyext(int argc,const t_atom *argv,bool sig): #else #pragma message("Adding current dir to path is not implemented") #endif - const t_atom &scr = argv[apre]; - - if(!IsString(scr)) - post("%s - script name argument is invalid",thisName()); - else { + const t_symbol *scr = GetASymbol(argv[apre]); + if(scr) { GetModulePath(GetString(scr),dir,sizeof(dir)); // add to path AddToPath(dir); - SetArgs(0,NULL); +// SetArgs(0,NULL); ImportModule(GetString(scr)); } + else + post("%s - script name argument is invalid",thisName()); ++apre; // check for alias creation names - if(strrchr(thisName(),'.')) clname = &scr; + if(strrchr(thisName(),'.')) clname = scr; } Register("_pyext"); if(argc > apre || clname) { - if(!clname) clname = &argv[apre++]; + if(!clname) clname = GetASymbol(argv[apre++]); // class name - if(!IsString(*clname)) + if(!clname) post("%s - class name argument is invalid",thisName()); else - methname = GetSymbol(*clname); + methname = clname; } - if(argc > apre) args(argc-apre,argv+apre); + if(argc > apre) initargs(argc-apre,argv+apre); + + Report(); PyUnlock(state); } @@ -231,23 +232,27 @@ bool pyext::DoInit() // call init now, after _this has been set, which is // important for eventual callbacks from __init__ to c - PyObject *pargs = MakePyArgs(NULL,args.Count(),args.Atoms(),-1,true); - if(!pargs) PyErr_Print(); - - PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref - if(init) { - if(PyMethod_Check(init)) { - PyObject *res = PyObject_CallObject(init,pargs); - if(!res) - PyErr_Print(); - else - Py_DECREF(res); - } - Py_DECREF(init); - } - - Py_XDECREF(pargs); - return true; + PyObject *pargs = MakePyArgs(NULL,initargs.Count(),initargs.Atoms(),-1,true); + if(pargs) { + bool ok = true; + + PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref + if(init) { + if(PyMethod_Check(init)) { + PyObject *res = PyObject_CallObject(init,pargs); + if(!res) + ok = false; + else + Py_DECREF(res); + } + Py_DECREF(init); + } + + Py_DECREF(pargs); + return ok; + } + else + return false; } void pyext::DoExit() @@ -269,6 +274,7 @@ void pyext::DoExit() Py_DECREF(objdel); } else + // _del has not been found - don't care PyErr_Clear(); gcrun = pyobj->ob_refcnt > 1; @@ -280,7 +286,7 @@ void pyext::DoExit() } } -void pyext::InitInOut(int &inl,int &outl) +bool pyext::InitInOut(int &inl,int &outl) { if(inl >= 0) { // set number of inlets @@ -293,8 +299,9 @@ void pyext::InitInOut(int &inl,int &outl) FLEXT_ASSERT(!ret); } - DoInit(); // call __init__ constructor // __init__ can override the number of inlets and outlets + if(!DoInit()) // call __init__ constructor + return false; if(inl < 0) { // get number of inlets @@ -330,6 +337,8 @@ void pyext::InitInOut(int &inl,int &outl) else PyErr_Clear(); } + + return true; } bool pyext::MakeInstance() @@ -358,22 +367,26 @@ bool pyext::MakeInstance() return false; } -void pyext::Reload() +bool pyext::Reload() { DoExit(); // by here, the Python class destructor should have been called! - SetArgs(0,NULL); - ReloadModule(); +// SetArgs(0,NULL); + bool ok = ReloadModule(); - MakeInstance(); + if(ok) ok = MakeInstance(); + + if(ok) { + int inl = -1,outl = -1; + ok = InitInOut(inl,outl); - int inl = -1,outl = -1; - InitInOut(inl,outl); + if(inl != inlets || outl != outlets) + post("%s - Inlet and outlet count can't be changed by reload",thisName()); + } - if(inl != inlets || outl != outlets) - post("%s - Inlet and outlet count can't be changed by reload",thisName()); + return ok; } @@ -390,13 +403,9 @@ void pyext::m_reload() SetThis(); - PyUnlock(state); -} + Report(); -void pyext::m_reload_(int argc,const t_atom *argv) -{ - args(argc,argv); - m_reload(); + PyUnlock(state); } void pyext::m_get(const t_symbol *s) @@ -404,26 +413,19 @@ void pyext::m_get(const t_symbol *s) PyThreadState *state = PyLockSys(); PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */ - if(!pvar) { - PyErr_Clear(); // no method found - post("%s - get: Python variable %s not found",thisName(),GetString(s)); - } - else { - AtomList *lst = GetPyArgs(pvar); - if(lst) { + if(pvar) { + AtomListStatic<16> lst; + if(GetPyArgs(lst,pvar,1)) { // dump value to attribute outlet - AtomAnything out(sym_get,lst->Count()+1); - SetSymbol(out[0],s); - out.Set(lst->Count(),lst->Atoms(),1); - delete lst; - - ToOutAnything(GetOutAttr(),out); + SetSymbol(lst[0],s); + ToOutAnything(GetOutAttr(),sym_get,lst.Count(),lst.Atoms()); } - else - post("%s - get: List could not be created",thisName()); + Py_DECREF(pvar); } + Report(); + PyUnlock(state); } @@ -437,16 +439,9 @@ void pyext::m_set(int argc,const t_atom *argv) post("%s - set: variables with leading _ are reserved and can't be set",thisName()); else { char *ch = const_cast<char *>(GetString(argv[0])); - if(!PyObject_HasAttrString(pyobj,ch)) { - PyErr_Clear(); // no method found - post("%s - set: Python variable %s not found",thisName(),ch); - } - else { + if(PyObject_HasAttrString(pyobj,ch)) { PyObject *pval = MakePyArgs(NULL,argc-1,argv+1,-1,false); - - if(!pval) - PyErr_Print(); - else { + if(pval) { if(PySequence_Size(pval) == 1) { // reduce lists of one element to element itself @@ -461,6 +456,8 @@ void pyext::m_set(int argc,const t_atom *argv) } } + Report(); + PyUnlock(state); } diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h index 3c6a86b5..4dd97983 100644 --- a/externals/grill/py/source/pyext.h +++ b/externals/grill/py/source/pyext.h @@ -62,8 +62,8 @@ protected: void m_help(); void m_reload(); - void m_reload_(int argc,const t_atom *argv); - void ms_args(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); } + void m_reload_(int argc,const t_atom *argv) { initargs(argc,argv); m_reload(); } + void ms_initargs(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); } void m_dir_() { m__dir(pyobj); } void mg_dir_(AtomList &lst) { GetDir(pyobj,lst); } void m_doc_() { m__doc(((PyInstanceObject *)pyobj)->in_class->cl_dict); } @@ -76,7 +76,9 @@ protected: int inlets,outlets; int siginlets,sigoutlets; - virtual void Reload(); + AtomListStatic<16> initargs; + + virtual bool Reload(); virtual bool DoInit(); virtual void DoExit(); @@ -91,9 +93,7 @@ private: void ClearBinding(); bool MakeInstance(); - void InitInOut(int &inlets,int &outlets); - - AtomList args; + bool InitInOut(int &inlets,int &outlets); static PyObject *class_obj,*class_dict; static PyMethodDef attr_tbl[],meth_tbl[]; @@ -124,8 +124,8 @@ private: FLEXT_CALLGET_V(mg_dir_) FLEXT_CALLBACK(m_doc_) - FLEXT_ATTRGET_V(args) - FLEXT_CALLSET_V(ms_args) + FLEXT_ATTRGET_V(initargs) + FLEXT_CALLSET_V(ms_initargs) FLEXT_CALLBACK_S(m_get) FLEXT_CALLBACK_V(m_set) |