Update of /cvsroot/pure-data/externals/grill/py/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24330/source
Modified Files: bound.cpp clmeth.cpp main.cpp main.h modmeth.cpp py.cpp pyargs.cpp pyext.cpp pyext.h Added Files: pyprefix.h pysymbol.cpp pysymbol.h Log Message: added symbol type fixed incorrect unbinding of instance methods fixes for symbol type little restructuring
Index: clmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** clmeth.cpp 9 Jan 2005 04:59:30 -0000 1.12 --- clmeth.cpp 11 Jan 2005 04:59:27 -0000 1.13 *************** *** 14,20 **** PyMethodDef pyext::meth_tbl[] = { {"__init__", pyext::pyext__init__, METH_VARARGS, "Constructor"}, {"__del__", pyext::pyext__del__, METH_VARARGS, "Destructor"}, ! {"_outlet", pyext::pyext_outlet, METH_VARARGS,"Send message to outlet"}, #if FLEXT_SYS == FLEXT_SYS_PD --- 14,21 ---- PyMethodDef pyext::meth_tbl[] = { + /* {"__init__", pyext::pyext__init__, METH_VARARGS, "Constructor"}, {"__del__", pyext::pyext__del__, METH_VARARGS, "Destructor"}, ! */ {"_outlet", pyext::pyext_outlet, METH_VARARGS,"Send message to outlet"}, #if FLEXT_SYS == FLEXT_SYS_PD *************** *** 57,60 **** --- 58,62 ---- ;
+ /* PyObject* pyext::pyext__init__(PyObject *,PyObject *args) { *************** *** 72,75 **** --- 74,78 ---- return Py_None; } + */
PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) *************** *** 83,86 **** --- 86,91 ----
bool handled = false; + + /* if(PyString_Check(name)) { char* sname = PyString_AsString(name); *************** *** 89,93 **** } } ! if(!handled) { if(PyInstance_Check(self)) --- 94,98 ---- } } ! */ if(!handled) { if(PyInstance_Check(self)) *************** *** 110,115 ****
if(PyString_Check(name)) { ! char* sname = PyString_AsString(name); ! if (sname) { if(!strcmp(sname,"_shouldexit")) { pyext *ext = GetThis(self); --- 115,120 ----
if(PyString_Check(name)) { ! char* sname = PyString_AS_STRING(name); ! if(sname) { if(!strcmp(sname,"_shouldexit")) { pyext *ext = GetThis(self); *************** *** 123,128 **** if(!ret) { #if PY_VERSION_HEX >= 0x02020000 ! // \todo borrowed or new??? ! ret = PyObject_GenericGetAttr(self,name); #else if(PyInstance_Check(self)) --- 128,132 ---- if(!ret) { #if PY_VERSION_HEX >= 0x02020000 ! ret = PyObject_GenericGetAttr(self,name); // new reference (?) #else if(PyInstance_Check(self)) *************** *** 142,155 **** FLEXT_ASSERT(PyTuple_Check(args));
// borrowed references! ! PyObject *self = PyTuple_GetItem(args,0); ! PyObject *outl = PyTuple_GetItem(args,1); if( ! self && PyInstance_Check(self) && ! outl && PyInt_Check(outl) ) { pyext *ext = GetThis(self);
- int sz = PyTuple_Size(args); PyObject *val;
--- 146,161 ---- FLEXT_ASSERT(PyTuple_Check(args));
+ int sz = PyTuple_GET_SIZE(args); + // borrowed references! ! PyObject *self,*outl; ! if( ! sz >= 2 && ! (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) && ! (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ) { pyext *ext = GetThis(self);
PyObject *val;
*************** *** 157,161 **** sz == 3 && PySequence_Check( ! val = PyTuple_GetItem(args,2) // borrow reference );
--- 163,167 ---- sz == 3 && PySequence_Check( ! val = PyTuple_GET_ITEM(args,2) // borrow reference );
*************** *** 256,265 **** FLEXT_ASSERT(PyTuple_Check(args));
bool ok = false; ! PyObject *self = PyTuple_GetItem(args,0); // borrowed ref ! if(self && PyInstance_Check(self)) { pyext *ext = GetThis(self);
- int sz = PySequence_Size(args); PyObject *val;
--- 262,275 ---- FLEXT_ASSERT(PyTuple_Check(args));
+ int sz = PyTuple_GET_SIZE(args); + bool ok = false; ! PyObject *self; // borrowed ref ! if( ! sz >= 1 && ! (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) ! ) { pyext *ext = GetThis(self);
PyObject *val;
*************** *** 267,271 **** sz == 2 && PySequence_Check( ! val = PyTuple_GetItem(args,1) // borrowed ref );
--- 277,281 ---- sz == 2 && PySequence_Check( ! val = PyTuple_GET_ITEM(args,1) // borrowed ref );
--- NEW FILE: pyprefix.h --- /*
py/pyext - python script object for PD and MaxMSP
Copyright (c)2002-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution.
*/
#ifndef __PREFIX_H #define __PREFIX_H
#define FLEXT_ATTRIBUTES 1 #include <flext.h>
#if FLEXT_OS == FLEXT_OS_MAC #include <Python/Python.h> #else #include <Python.h> #endif
#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif
#endif
Index: main.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.cpp,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** main.cpp 10 Jan 2005 05:00:56 -0000 1.20 --- main.cpp 11 Jan 2005 04:59:27 -0000 1.21 *************** *** 57,60 **** --- 57,62 ----
+ void initsymbol(); + void py::lib_setup() { *************** *** 77,82 ****
#ifdef FLEXT_DEBUG ! // Py_DebugFlag = 1; ! Py_VerboseFlag = 1; #endif
--- 79,83 ----
#ifdef FLEXT_DEBUG ! // Py_VerboseFlag = 1; #endif
*************** *** 100,103 **** --- 101,116 ---- PyModule_AddStringConstant(module_obj,"__doc__",(char *)py_doc);
+ // add symbol type + initsymbol(); + PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type); + + // pre-defined symbols + PyModule_AddObject(module_obj,"_s_",(PyObject *)pySymbol__); + PyModule_AddObject(module_obj,"_s_bang",(PyObject *)pySymbol_bang); + PyModule_AddObject(module_obj,"_s_list",(PyObject *)pySymbol_list); + PyModule_AddObject(module_obj,"_s_symbol",(PyObject *)pySymbol_symbol); + PyModule_AddObject(module_obj,"_s_float",(PyObject *)pySymbol_float); + PyModule_AddObject(module_obj,"_s_int",(PyObject *)pySymbol_int); + // redirect stdout PyObject* py_out; *************** *** 125,128 **** --- 138,151 ----
+ void py::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 + } + py::py(): module(NULL), *************** *** 151,155 **** // Wait forever post("%s - Waiting for thread termination!",thisName()); ! while(thrcount) Sleep(0.2f); post("%s - Okay, all threads have terminated",thisName()); } --- 174,178 ---- // Wait forever post("%s - Waiting for thread termination!",thisName()); ! while(thrcount) Sleep(0.01f); post("%s - Okay, all threads have terminated",thisName()); } *************** *** 199,203 **** if(docf && PyString_Check(docf)) { post(""); ! const char *s = PyString_AsString(docf);
// FIX: Python doc strings can easily be larger than 1k characters --- 222,226 ---- if(docf && PyString_Check(docf)) { post(""); ! const char *s = PyString_AS_STRING(docf);
// FIX: Python doc strings can easily be larger than 1k characters *************** *** 227,230 **** --- 250,257 ---- }
+ void py::m_click() + { + // this should once open the editor.... + }
void py::SetArgs(int argc,const t_atom *argv) *************** *** 252,257 ****
module = PyImport_ImportModule((char *)name); // increases module_obj ref count by one ! if (!module) { ! PyErr_Print(); dict = NULL; --- 279,283 ----
module = PyImport_ImportModule((char *)name); // increases module_obj ref count by one ! if(!module) { PyErr_Print(); dict = NULL; *************** *** 265,269 **** if(!module) return;
! assert(dict && module_obj && module_dict);
Py_DECREF(module); --- 291,295 ---- if(!module) return;
! FLEXT_ASSERT(dict && module_obj && module_dict);
Py_DECREF(module); *************** *** 344,358 **** PyObject *pobj = PySys_GetObject("path"); if(pobj && PyList_Check(pobj)) { ! int i,n = PyList_Size(pobj); ! for(i = 0; i < n; ++i) { ! PyObject *pt = PyList_GetItem(pobj,i); // borrowed reference ! if(PyString_Check(pt) && !strcmp(dir,PyString_AS_STRING(pt))) break; ! } ! if(i == n) { // string is not yet existent in path ! PyObject *ps = PyString_FromString(dir); ! PyList_Append(pobj,ps); ! } } ! PySys_SetObject("path",pobj); } } --- 370,379 ---- PyObject *pobj = PySys_GetObject("path"); if(pobj && PyList_Check(pobj)) { ! PyObject *ps = PyString_FromString(dir); ! if(!PySequence_Contains(pobj,ps)) ! PyList_Append(pobj,ps); // makes new reference ! Py_DECREF(ps); } ! PySys_SetObject("path",pobj); // steals reference to pobj } } *************** *** 379,385 **** FLEXT_ASSERT(PyTuple_Check(args));
! int sz = PyTuple_Size(args); for(int i = 0; i < sz; ++i) { ! PyObject *val = PyTuple_GetItem(args,i); // borrowed reference PyObject *str = PyObject_Str(val); // new reference char *cstr = PyString_AS_STRING(str); --- 400,407 ---- FLEXT_ASSERT(PyTuple_Check(args));
! const int sz = PyTuple_GET_SIZE(args); ! for(int i = 0; i < sz; ++i) { ! PyObject *val = PyTuple_GET_ITEM(args,i); // borrowed reference PyObject *str = PyObject_Str(val); // new reference char *cstr = PyString_AS_STRING(str);
Index: pyargs.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyargs.cpp,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** pyargs.cpp 9 Jan 2005 04:59:30 -0000 1.10 --- pyargs.cpp 11 Jan 2005 04:59:27 -0000 1.11 *************** *** 13,17 **** static PyObject *MakePyAtom(const t_atom &at) { ! if(flext::IsSymbol(at)) return PyString_FromString(flext::GetString(at)); // else if(flext::IsPointer(at)) return NULL; // not handled else if(flext::CanbeInt(at) && flext::CanbeFloat(at)) { --- 13,18 ---- static PyObject *MakePyAtom(const t_atom &at) { ! if(flext::IsSymbol(at)) ! return pySymbol_FromSymbol(flext::GetSymbol(at)); // else if(flext::IsPointer(at)) return NULL; // not handled else if(flext::CanbeInt(at) && flext::CanbeFloat(at)) { *************** *** 46,55 **** int pix = 0;
! if(inlet >= 0) { ! PyObject *pValue = PyInt_FromLong(inlet); ! ! // reference stolen: ! PyTuple_SetItem(pArgs, pix++, pValue); ! }
int ix; --- 47,52 ---- int pix = 0;
! if(inlet >= 0) ! PyTuple_SetItem(pArgs, pix++, PyInt_FromLong(inlet));
int ix; *************** *** 58,67 **** else tmp = PyTuple_New(argc+(any?1:0)),ix = 0;
! if(any) { ! PyObject *pValue = PyString_FromString(GetString(s)); ! ! // reference stolen here: ! PyTuple_SetItem(tmp, ix++, pValue); ! }
for(int i = 0; i < argc; ++i) { --- 55,60 ---- else tmp = PyTuple_New(argc+(any?1:0)),ix = 0;
! if(any) ! PyTuple_SET_ITEM(tmp, ix++, pySymbol_FromSymbol(s));
for(int i = 0; i < argc; ++i) { *************** *** 73,81 ****
/* pValue reference stolen here: */ ! PyTuple_SetItem(tmp, ix++, pValue); }
if(tmp != pArgs) { ! PyTuple_SetItem(pArgs, pix++, tmp); #if PY_VERSION_HEX >= 0x02020000 _PyTuple_Resize(&pArgs,pix); --- 66,74 ----
/* pValue reference stolen here: */ ! PyTuple_SET_ITEM(tmp, ix++, pValue); }
if(tmp != pArgs) { ! PyTuple_SET_ITEM(pArgs, pix++, tmp); #if PY_VERSION_HEX >= 0x02020000 _PyTuple_Resize(&pArgs,pix); *************** *** 127,131 **** 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(PyString_Check(arg)) SetString((*ret)[ix],PyString_AsString(arg)); else if(ix == 0 && self && PyInstance_Check(arg)) { // assumed to be self ... that should be checked _somehow_ !!! --- 120,125 ---- 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)); else if(ix == 0 && self && PyInstance_Check(arg)) { // assumed to be self ... that should be checked _somehow_ !!! *************** *** 137,141 **** PyObject *stp = tp?PyObject_Str(tp):NULL; char *tmp = ""; ! if(stp) tmp = PyString_AsString(stp); post("py/pyext: Could not convert argument %s",tmp); Py_XDECREF(stp); --- 131,135 ---- PyObject *stp = tp?PyObject_Str(tp):NULL; char *tmp = ""; ! if(stp) tmp = PyString_AS_STRING(stp); post("py/pyext: Could not convert argument %s",tmp); Py_XDECREF(stp);
Index: modmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** modmeth.cpp 9 Jan 2005 04:59:30 -0000 1.13 --- modmeth.cpp 11 Jan 2005 04:59:27 -0000 1.14 *************** *** 108,115 **** FLEXT_ASSERT(PyTuple_Check(args));
! PyObject *name = PyTuple_GetItem(args,0); // borrowed reference ! if(name && PyString_Check(name)) { ! const t_symbol *recv = MakeSymbol(PyString_AsString(name)); ! int sz = PySequence_Size(args); PyObject *val;
--- 108,118 ---- FLEXT_ASSERT(PyTuple_Check(args));
! const int sz = PyTuple_GET_SIZE(args); ! ! const t_symbol *recv; ! if( ! sz >= 1 && ! (recv = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL ! ) { PyObject *val;
*************** *** 117,121 **** sz == 2 && PySequence_Check( ! val = PyTuple_GetItem(args,1) // borrowed ref );
--- 120,124 ---- sz == 2 && PySequence_Check( ! val = PyTuple_GET_ITEM(args,1) // borrowed ref );
*************** *** 169,178 **** FLEXT_ASSERT(PyTuple_Check(args));
PyObject *ret; - PyObject *name = PyTuple_GetItem(args,0); // borrowed reference - - if(name && PyString_Check(name)) { - const t_symbol *sym = MakeSymbol(PyString_AsString(name));
float f; if(value_getfloat(const_cast<t_symbol *>(sym),&f)) { --- 172,183 ---- FLEXT_ASSERT(PyTuple_Check(args));
+ const int sz = PyTuple_GET_SIZE(args); + const t_symbol *sym; PyObject *ret;
+ if( + sz == 1 && + (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL + ) { float f; if(value_getfloat(const_cast<t_symbol *>(sym),&f)) { *************** *** 194,201 **** FLEXT_ASSERT(PyTuple_Check(args));
! PyObject *name = PyTuple_GetItem(args,0); // borrowed reference ! PyObject *val = PyTuple_GetItem(args,1); // borrowed reference ! if(name && val && PyString_Check(name) && PyNumber_Check(val)) { ! const t_symbol *sym = MakeSymbol(PyString_AsString(name)); float f = (float)PyFloat_AsDouble(val);
--- 199,211 ---- FLEXT_ASSERT(PyTuple_Check(args));
! const int sz = PyTuple_GET_SIZE(args); ! const t_symbol *sym; ! PyObject *val; // borrowed reference ! ! if( ! sz == 2 && ! (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL && ! PyNumber_Check(val = PyTuple_GET_ITEM(args,1)) ! ) { float f = (float)PyFloat_AsDouble(val);
Index: bound.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/bound.cpp,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** bound.cpp 9 Jan 2005 04:59:30 -0000 1.13 --- bound.cpp 11 Jan 2005 04:59:27 -0000 1.14 *************** *** 14,18 **** #include <set>
! typedef std::set<PyObject *> FuncSet;
struct bounddata --- 14,56 ---- #include <set>
! class MethodCompare: ! public std::less<PyObject *> ! { ! public: ! bool operator()(PyObject *a,PyObject *b) const ! { ! if(PyMethod_Check(a)) ! if(PyMethod_Check(b)) { ! // both are methods ! PyObject *sa = PyMethod_GET_SELF(a); ! PyObject *sb = PyMethod_GET_SELF(b); ! if(sa) ! if(sb) { ! // both have self ! if(sa == sb) ! return PyMethod_GET_FUNCTION(a) < PyMethod_GET_FUNCTION(b); ! else ! return sa < sb; ! } ! else ! return false; ! else ! if(sb) ! return true; ! else ! return PyMethod_GET_FUNCTION(a) < PyMethod_GET_FUNCTION(b); ! } ! else ! return false; ! else ! if(PyMethod_Check(b)) ! return true; ! else ! // both are functions ! return a < b; ! } ! }; ! ! typedef std::set<PyObject *,MethodCompare> FuncSet;
struct bounddata *************** *** 34,41 **** for(FuncSet::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) { PyObject *ret = PyObject_CallObject(*it,args); ! if(!ret) { PyErr_Print(); ! } ! Py_XDECREF(ret); }
--- 72,79 ---- for(FuncSet::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) { PyObject *ret = PyObject_CallObject(*it,args); ! if(!ret) PyErr_Print(); ! else ! Py_DECREF(ret); }
*************** *** 48,54 **** PyObject *pyext::pyext_bind(PyObject *,PyObject *args) { ! PyObject *self,*meth; ! char *name; ! if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth)) post("py/pyext - Wrong arguments!"); else if(!PyInstance_Check(self) || !(PyMethod_Check(meth) || PyFunction_Check(meth))) { --- 86,91 ---- 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))) { *************** *** 56,86 **** } else { ! const t_symbol *recv = MakeSymbol(name); ! /* ! if(GetBound(recv)) ! post("py/pyext - Symbol "%s" is already hooked",GetString(recv)); ! */ ! // make a proxy object
! if(PyMethod_Check(meth)) { ! PyObject *no = PyObject_GetAttrString(meth,"__name__"); ! meth = PyObject_GetAttr(self,no); ! Py_DECREF(no); ! }
void *data = NULL; ! if(GetThis(self)->GetBoundMethod(recv,boundmeth,data)) { // already bound to that symbol and function bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL && bdt->self == self); ! bdt->funcs.insert(meth); } else { bounddata *data = new bounddata; data->self = self; data->funcs.insert(meth); - GetThis(self)->BindMethod(recv,boundmeth,data);
! Py_INCREF(self); // self is borrowed reference } } --- 93,122 ---- } else { ! py *th = GetThis(self); ! FLEXT_ASSERT(th);
! const t_symbol *recv = pyObject_AsSymbol(name);
void *data = NULL; ! if(recv && th->GetBoundMethod(recv,boundmeth,data)) { // already bound to that symbol and function bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL && bdt->self == self); ! ! FuncSet::iterator it = bdt->funcs.find(meth); ! if(it == bdt->funcs.end()) { ! bdt->funcs.insert(meth); ! Py_INCREF(meth); ! } } else { + Py_INCREF(self); // self is borrowed reference + Py_INCREF(meth); + bounddata *data = new bounddata; data->self = self; data->funcs.insert(meth);
! th->BindMethod(recv,boundmeth,data); } } *************** *** 92,98 **** PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) { ! PyObject *self,*meth; ! char *name; ! if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth)) post("py/pyext - Wrong arguments!"); else if(!PyInstance_Check(self) || !(PyMethod_Check(meth) || PyFunction_Check(meth))) { --- 128,133 ---- 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))) { *************** *** 100,123 **** } else { ! const t_symbol *recv = MakeSymbol(name); ! if(PyMethod_Check(meth)) { ! PyObject *no = PyObject_GetAttrString(meth,"__name__"); ! meth = PyObject_GetAttr(self,no); // meth is given a new reference! ! Py_DECREF(no); ! }
void *data = NULL; ! if(GetThis(self)->UnbindMethod(recv,boundmeth,&data)) { bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL);
- if(PyMethod_Check(meth)) Py_DECREF(meth); - // erase from map ! bdt->funcs.erase(meth);
if(bdt->funcs.empty()) { Py_DECREF(bdt->self); delete bdt; } } --- 135,164 ---- } else { ! py *th = GetThis(self); ! FLEXT_ASSERT(th); ! ! const t_symbol *recv = pyObject_AsSymbol(name);
void *data = NULL; ! if(recv && th->GetBoundMethod(recv,boundmeth,data)) { bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL);
// erase from map ! // ATTENTION: meth is different from the element found in the map ! // it just points to the same instance method ! FuncSet::iterator it = bdt->funcs.find(meth); ! if(it != bdt->funcs.end()) { ! Py_DECREF(*it); ! bdt->funcs.erase(it); ! } ! else ! post("py/pyext - Function to unbind couldn't be found");
if(bdt->funcs.empty()) { Py_DECREF(bdt->self); delete bdt; + + th->UnbindMethod(recv,boundmeth,NULL); } } *************** *** 143,153 **** bounddata *bdt = (bounddata *)data; if(bdt) { ! for(FuncSet::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it) { ! PyObject *func = *it; ! if(PyMethod_Check(func)) Py_DECREF(func); ! }
Py_DECREF(bdt->self); ! if(data) delete bdt; } } --- 184,192 ---- bounddata *bdt = (bounddata *)data; if(bdt) { ! for(FuncSet::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it) ! Py_DECREF(*it);
Py_DECREF(bdt->self); ! delete bdt; } }
Index: pyext.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** pyext.cpp 10 Jan 2005 05:00:56 -0000 1.24 --- pyext.cpp 11 Jan 2005 04:59:27 -0000 1.25 *************** *** 21,38 **** sym_get = flext::MakeSymbol("get");
- FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); ! FLEXT_CADDMETHOD_(c,0,"dir",m_dir); ! FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_); ! FLEXT_CADDMETHOD_(c,0,"doc",m_doc); FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_); ! ! FLEXT_CADDATTR_VAR(c,"args",args,ms_args); FLEXT_CADDATTR_GET(c,"dir+",mg_dir_);
! #ifdef FLEXT_THREADS ! FLEXT_CADDATTR_VAR1(c,"detach",detach); ! FLEXT_CADDMETHOD_(c,0,"stop",m_stop); ! #endif
FLEXT_CADDMETHOD_(c,0,"get",m_get); --- 21,31 ---- sym_get = flext::MakeSymbol("get");
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_CADDATTR_GET(c,"dir+",mg_dir_);
! FLEXT_CADDATTR_VAR(c,"args",args,ms_args);
FLEXT_CADDMETHOD_(c,0,"get",m_get); *************** *** 173,228 **** MakeInstance();
! if(pyobj) { ! if(inlets >= 0) { ! // set number of inlets ! PyObject *res = PyInt_FromLong(inlets); ! int ret = PyObject_SetAttrString(pyobj,"_inlets",res); ! FLEXT_ASSERT(!ret); ! } ! if(outlets >= 0) { ! // set number of outlets ! PyObject *res = PyInt_FromLong(outlets); ! int ret = PyObject_SetAttrString(pyobj,"_outlets",res); ! FLEXT_ASSERT(!ret); ! } ! ! DoInit(); // call __init__ constructor ! // __init__ can override the number of inlets and outlets ! ! if(inlets < 0) { ! // get number of inlets ! inlets = 1; ! PyObject *res = PyObject_GetAttrString(pyobj,"_inlets"); // get ref ! if(res) { ! if(PyCallable_Check(res)) { ! PyObject *fres = PyEval_CallObject(res,NULL); ! Py_DECREF(res); ! res = fres; ! } ! if(PyInt_Check(res)) ! inlets = PyInt_AsLong(res); ! Py_DECREF(res); ! } ! else ! PyErr_Clear(); ! } ! if(outlets < 0) { ! // get number of outlets ! outlets = 1; ! PyObject *res = PyObject_GetAttrString(pyobj,"_outlets"); // get ref ! if(res) { ! if(PyCallable_Check(res)) { ! PyObject *fres = PyEval_CallObject(res,NULL); ! Py_DECREF(res); ! res = fres; ! } ! if(PyInt_Check(res)) ! outlets = PyInt_AsLong(res); ! Py_DECREF(res); ! } ! else ! PyErr_Clear(); ! } ! } } else --- 166,171 ---- MakeInstance();
! if(pyobj) ! InitInOut(inlets,outlets); } else *************** *** 246,255 **** PyThreadState *state = PyLock();
! ClearBinding(); ! ! if(pyobj) { ! if(pyobj->ob_refcnt > 1) post("%s - Python object is still referenced",thisName()); ! Py_DECREF(pyobj); // opposite of SetClssMeth ! }
Unregister("_pyext"); --- 189,193 ---- PyThreadState *state = PyLock();
! DoExit();
Unregister("_pyext"); *************** *** 270,275 **** PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref if(init) { ! if(PyCallable_Check(init)) { ! PyObject *res = PyEval_CallObject(init,pargs); if(!res) PyErr_Print(); --- 208,213 ---- PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref if(init) { ! if(PyMethod_Check(init)) { ! PyObject *res = PyObject_CallObject(init,pargs); if(!res) PyErr_Print(); *************** *** 284,287 **** --- 222,305 ---- }
+ void pyext::DoExit() + { + ClearBinding(); + + if(pyobj) { + if(pyobj->ob_refcnt > 1) { + post("%s - Python object is still referenced",thisName()); + + // Force-quit object: + // call __del__ manually + // this is dangerous, because it could get called a second time + // if object really has no more references then + PyObject *meth = PyObject_GetAttrString(pyobj,"__del__"); // get ref + if(meth) { + if(PyMethod_Check(meth)) { + PyObject *res = PyObject_CallObject(meth,NULL); + if(!res) + PyErr_Print(); + else + Py_DECREF(res); + } + Py_DECREF(meth); + } + } + Py_DECREF(pyobj); // opposite of SetClssMeth + } + } + + void pyext::InitInOut(int &inl,int &outl) + { + if(inl >= 0) { + // set number of inlets + int ret = PyObject_SetAttrString(pyobj,"_inlets",PyInt_FromLong(inl)); + FLEXT_ASSERT(!ret); + } + if(outl >= 0) { + // set number of outlets + int ret = PyObject_SetAttrString(pyobj,"_outlets",PyInt_FromLong(outl)); + FLEXT_ASSERT(!ret); + } + + DoInit(); // call __init__ constructor + // __init__ can override the number of inlets and outlets + + if(inl < 0) { + // get number of inlets + inl = 1; + PyObject *res = PyObject_GetAttrString(pyobj,"_inlets"); // get ref + if(res) { + if(PyCallable_Check(res)) { + PyObject *fres = PyEval_CallObject(res,NULL); + Py_DECREF(res); + res = fres; + } + if(PyInt_Check(res)) + inl = PyInt_AS_LONG(res); + Py_DECREF(res); + } + else + PyErr_Clear(); + } + if(outl < 0) { + // get number of outlets + outl = 1; + PyObject *res = PyObject_GetAttrString(pyobj,"_outlets"); // get ref + if(res) { + if(PyCallable_Check(res)) { + PyObject *fres = PyEval_CallObject(res,NULL); + Py_DECREF(res); + res = fres; + } + if(PyInt_Check(res)) + outl = PyInt_AS_LONG(res); + Py_DECREF(res); + } + else + PyErr_Clear(); + } + } + bool pyext::MakeInstance() { *************** *** 312,317 **** void pyext::Reload() { ! ClearBinding(); ! Py_XDECREF(pyobj);
// by here, the Python class destructor should have been called! --- 330,334 ---- void pyext::Reload() { ! DoExit();
// by here, the Python class destructor should have been called! *************** *** 321,324 **** --- 338,347 ---- MakeInstance(); + + 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()); }
Index: pyext.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.h,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** pyext.h 9 Jan 2005 04:59:30 -0000 1.18 --- pyext.h 11 Jan 2005 04:59:27 -0000 1.19 *************** *** 71,74 **** --- 71,76 ---- bool MakeInstance(); bool DoInit(); + void DoExit(); + void InitInOut(int &inlets,int &outlets);
AtomList args;
--- NEW FILE: pysymbol.cpp --- /*
py/pyext - python script object for PD and Max/MSP
Copyright (c)2002-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution.
*/
#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 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(a); bool ret; switch(cmp) { case Py_LT: ret = asym < bsym; case Py_LE: ret = asym <= bsym; case Py_EQ: ret = asym == bsym; case Py_NE: ret = asym != bsym; case Py_GT: ret = asym > bsym; case Py_GE: ret = asym >= bsym; } 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); }
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*/ 0, /*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 */ 0, /* 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) FLEXT_ASSERT(false); else 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: main.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.h,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** main.h 10 Jan 2005 05:00:56 -0000 1.27 --- main.h 11 Jan 2005 04:59:27 -0000 1.28 *************** *** 12,23 **** #define __MAIN_H
! #define FLEXT_ATTRIBUTES 1 ! ! #include <flext.h> ! #if FLEXT_OS == FLEXT_OS_MAC ! #include <Python/Python.h> ! #else ! #include <Python.h> ! #endif
#if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX --- 12,17 ---- #define __MAIN_H
! #include "pyprefix.h" ! #include "pysymbol.h"
#if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX *************** *** 25,32 **** #endif
- #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) - #error You need at least flext version 0.5.0 - #endif - #define PY__VERSION "0.2.0pre"
--- 19,22 ---- *************** *** 62,66 **** public flext_base { ! FLEXT_HEADER(py,flext_base)
public: --- 52,56 ---- public flext_base { ! FLEXT_HEADER_S(py,flext_base,Setup)
public: *************** *** 191,196 ****
protected: - // callbacks
FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(respond) --- 181,190 ----
protected:
+ virtual void m_click(); + + static void Setup(t_classid c); + + // callbacks FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(respond)
Index: py.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** py.cpp 10 Jan 2005 05:00:56 -0000 1.17 --- py.cpp 11 Jan 2005 04:59:27 -0000 1.18 *************** *** 82,98 **** void pyobj::Setup(t_classid c) { - FLEXT_CADDBANG(c,0,m_bang); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); ! FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); ! FLEXT_CADDMETHOD_(c,0,"set",m_set); ! FLEXT_CADDMETHOD_(c,0,"doc",m_doc); FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_); - #ifdef FLEXT_THREADS - FLEXT_CADDATTR_VAR1(c,"detach",detach); - FLEXT_CADDMETHOD_(c,0,"stop",m_stop); - #endif - FLEXT_CADDMETHOD_(c,0,"dir",m_dir); FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
FLEXT_CADDMETHOD_(c,1,"float",m_py_float); FLEXT_CADDMETHOD_(c,1,"int",m_py_int); --- 82,93 ---- void pyobj::Setup(t_classid c) { 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_CADDBANG(c,0,m_bang); + FLEXT_CADDMETHOD_(c,0,"set",m_set); + FLEXT_CADDMETHOD_(c,1,"float",m_py_float); FLEXT_CADDMETHOD_(c,1,"int",m_py_int);
--- NEW FILE: pysymbol.h --- /*
py/pyext - python script object for PD and Max/MSP
Copyright (c)2002-2005 Thomas Grill (gr@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"
typedef struct { PyObject_HEAD /* Type-specific fields go here. */ const t_symbol *sym; } pySymbol;
extern PyTypeObject pySymbol_Type;
extern pySymbol *pySymbol__; extern pySymbol *pySymbol_bang; extern pySymbol *pySymbol_list; extern pySymbol *pySymbol_symbol; extern pySymbol *pySymbol_float; extern pySymbol *pySymbol_int;
#define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type) #define pySymbol_CheckExact(op) ((op)->ob_type == &PySymbol_Type)
PyObject *pySymbol_FromSymbol(const t_symbol *sym);
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); }