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(a)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(a)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(a)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);
}