aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--externals/grill/py/maxmsp/thread-1.mxbbin3172 -> 3080 bytes
-rw-r--r--externals/grill/py/package.txt5
-rw-r--r--externals/grill/py/pd/sendrecv-1.pd10
-rw-r--r--externals/grill/py/py.vcproj11
-rw-r--r--externals/grill/py/readme.txt8
-rw-r--r--externals/grill/py/scripts/sendrecv.py15
-rw-r--r--externals/grill/py/source/bound.cpp121
-rw-r--r--externals/grill/py/source/clmeth.cpp42
-rw-r--r--externals/grill/py/source/main.cpp60
-rw-r--r--externals/grill/py/source/main.h22
-rw-r--r--externals/grill/py/source/modmeth.cpp36
-rw-r--r--externals/grill/py/source/py.cpp13
-rw-r--r--externals/grill/py/source/pyargs.cpp28
-rw-r--r--externals/grill/py/source/pyext.cpp167
-rw-r--r--externals/grill/py/source/pyext.h2
-rw-r--r--externals/grill/py/source/pyprefix.h27
-rw-r--r--externals/grill/py/source/pysymbol.cpp168
-rw-r--r--externals/grill/py/source/pysymbol.h57
18 files changed, 576 insertions, 216 deletions
diff --git a/externals/grill/py/maxmsp/thread-1.mxb b/externals/grill/py/maxmsp/thread-1.mxb
index 6a0b9bbe..de2d4716 100644
--- a/externals/grill/py/maxmsp/thread-1.mxb
+++ b/externals/grill/py/maxmsp/thread-1.mxb
Binary files differ
diff --git a/externals/grill/py/package.txt b/externals/grill/py/package.txt
index 03c6fa9d..8cbd70d6 100644
--- a/externals/grill/py/package.txt
+++ b/externals/grill/py/package.txt
@@ -4,7 +4,8 @@ BUILDTYPE=multi
BUILDDIR=build
SRCDIR=source
+PRECOMPILE=pyprefix.h
-SRCS= main.cpp py.cpp pyext.cpp modmeth.cpp clmeth.cpp register.cpp pyargs.cpp bound.cpp
+SRCS= main.cpp py.cpp pyext.cpp modmeth.cpp clmeth.cpp register.cpp pyargs.cpp bound.cpp pysymbol.cpp
-HDRS= main.h pyext.h
+HDRS= pyprefix.h main.h pyext.h pysymbol.h
diff --git a/externals/grill/py/pd/sendrecv-1.pd b/externals/grill/py/pd/sendrecv-1.pd
index 56810c74..ca399705 100644
--- a/externals/grill/py/pd/sendrecv-1.pd
+++ b/externals/grill/py/pd/sendrecv-1.pd
@@ -1,5 +1,5 @@
-#N canvas 145 126 642 317 12;
-#X msg 125 117 reload mi ma;
+#N canvas 145 126 650 325 12;
+#X msg 125 81 reload mi ma;
#X floatatom 48 238 5 0 0 0 - - -;
#X floatatom 297 239 5 0 0 0 - - -;
#X obj 297 263 s mi;
@@ -8,7 +8,7 @@
#X obj 382 240 r ma;
#X obj 48 262 s he;
#X obj 143 238 r hu;
-#X text 233 116 reload with different args;
+#X text 233 80 reload with different args;
#X msg 20 82 help;
#X msg 19 114 doc;
#X msg 58 114 doc+;
@@ -19,6 +19,8 @@
-1 0;
#X text 213 32 http://www.parasitaere-kapazitaeten.net;
#X text 213 16 Python script objects \, (C)2003-2004 Thomas Grill;
+#X msg 202 128 bind;
+#X msg 249 129 unbind;
#X connect 0 0 13 0;
#X connect 1 0 7 0;
#X connect 2 0 3 0;
@@ -27,3 +29,5 @@
#X connect 10 0 13 0;
#X connect 11 0 13 0;
#X connect 12 0 13 0;
+#X connect 19 0 13 1;
+#X connect 20 0 13 1;
diff --git a/externals/grill/py/py.vcproj b/externals/grill/py/py.vcproj
index ed43729f..38bfb17d 100644
--- a/externals/grill/py/py.vcproj
+++ b/externals/grill/py/py.vcproj
@@ -91,7 +91,7 @@
RuntimeLibrary="1"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="2"
- PrecompiledHeaderThrough=""
+ PrecompiledHeaderThrough="pyprefix.h"
BrowseInformation="0"
WarningLevel="3"
SuppressStartupBanner="TRUE"
@@ -1208,6 +1208,15 @@
RelativePath="source\pyext.h">
</File>
<File
+ RelativePath=".\source\pyprefix.h">
+ </File>
+ <File
+ RelativePath=".\source\pysymbol.cpp">
+ </File>
+ <File
+ RelativePath=".\source\pysymbol.h">
+ </File>
+ <File
RelativePath="source\register.cpp">
<FileConfiguration
Name="PD Debug|Win32">
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt
index 8db52f13..675a0a71 100644
--- a/externals/grill/py/readme.txt
+++ b/externals/grill/py/readme.txt
@@ -56,6 +56,9 @@ Version history:
- DEL: eliminated meaningless inchannels and outchannels methods
- ADD: enabled "int"-tags for pyext class functions
- ADD: py: when no function is given on the command line, let it be selected by message tag
+- FIX: __init__ wasn't called on reload
+- FIX: bound instance methods weren't correctly decref'd
+- ADD: Python symbol type
0.1.4:
- ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__)
@@ -123,10 +126,11 @@ general:
- better error reporting for runtime errors
features:
-- enable multiple interpreters?
+- enable multiple interpreters? ( -> not possible within one thread)
- stop individual threads
-- Python type for symbols
- support named (keyword) arguments (like attributes for messages)
+- shutdown hook for threaded Python apps
+
tests:
- check for python threading support
diff --git a/externals/grill/py/scripts/sendrecv.py b/externals/grill/py/scripts/sendrecv.py
index 0488359b..e3295ab6 100644
--- a/externals/grill/py/scripts/sendrecv.py
+++ b/externals/grill/py/scripts/sendrecv.py
@@ -43,7 +43,7 @@ class ex1(pyext._class):
# no inlets and outlets
- _inlets=0
+ _inlets=1
_outlets=0
recvname=""
@@ -66,21 +66,22 @@ class ex1(pyext._class):
if len(args) >= 1: self.recvname = args[0]
if len(args) >= 2: self.sendname = args[1]
+ self.bind_1()
+
+ def bind_1(self):
# bind functions to receiver names
# both are called upon message
self._bind(self.recvname,self.recv)
self._bind(self.recvname,recv_gl)
-
+
+ def unbind_1(self):
+ self._unbind(self.recvname,self.recv)
+ self._unbind(self.recvname,recv_gl)
def __del__(self):
"""Class destructor"""
- # you can but you don't need to
# unbinding is automatically done at destruction
- # you can also comment out the _unbind lines
- self._unbind(self.recvname,self.recv)
- self._unbind(self.recvname,recv_gl)
-
pass
diff --git a/externals/grill/py/source/bound.cpp b/externals/grill/py/source/bound.cpp
index ce17578c..5690e0b1 100644
--- a/externals/grill/py/source/bound.cpp
+++ b/externals/grill/py/source/bound.cpp
@@ -13,7 +13,45 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include <set>
-typedef std::set<PyObject *> FuncSet;
+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
{
@@ -33,10 +71,10 @@ bool pyext::boundmeth(flext_base *th,t_symbol *sym,int argc,t_atom *argv,void *d
// call all functions bound by this symbol
for(FuncSet::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) {
PyObject *ret = PyObject_CallObject(*it,args);
- if(!ret) {
+ if(!ret)
PyErr_Print();
- }
- Py_XDECREF(ret);
+ else
+ Py_DECREF(ret);
}
Py_XDECREF(args);
@@ -47,41 +85,39 @@ bool pyext::boundmeth(flext_base *th,t_symbol *sym,int argc,t_atom *argv,void *d
PyObject *pyext::pyext_bind(PyObject *,PyObject *args)
{
- PyObject *self,*meth;
- char *name;
- if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
+ 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))) {
post("py/pyext - Wrong argument types!");
}
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);
- }
+ py *th = GetThis(self);
+ FLEXT_ASSERT(th);
+
+ const t_symbol *recv = pyObject_AsSymbol(name);
void *data = NULL;
- if(GetThis(self)->GetBoundMethod(recv,boundmeth,data)) {
+ 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);
- bdt->funcs.insert(meth);
+
+ 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);
- GetThis(self)->BindMethod(recv,boundmeth,data);
- Py_INCREF(self); // self is borrowed reference
+ th->BindMethod(recv,boundmeth,data);
}
}
@@ -91,34 +127,39 @@ PyObject *pyext::pyext_bind(PyObject *,PyObject *args)
PyObject *pyext::pyext_unbind(PyObject *,PyObject *args)
{
- PyObject *self,*meth;
- char *name;
- if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
+ 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))) {
post("py/pyext - Wrong argument types!");
}
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);
- }
+ py *th = GetThis(self);
+ FLEXT_ASSERT(th);
+
+ const t_symbol *recv = pyObject_AsSymbol(name);
void *data = NULL;
- if(GetThis(self)->UnbindMethod(recv,boundmeth,&data)) {
+ if(recv && th->GetBoundMethod(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);
+ // 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);
}
}
}
@@ -142,13 +183,11 @@ void pyext::ClearBinding()
while(GetThis(pyobj)->UnbindMethod(sym,NULL,&data)) {
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);
- }
+ for(FuncSet::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it)
+ Py_DECREF(*it);
Py_DECREF(bdt->self);
- if(data) delete bdt;
+ delete bdt;
}
}
}
diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp
index 8423aa4b..92c6b4d3 100644
--- a/externals/grill/py/source/clmeth.cpp
+++ b/externals/grill/py/source/clmeth.cpp
@@ -13,9 +13,10 @@ WARRANTIES, see the file, "license.txt," in this distribution.
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
{"_tocanvas", pyext::pyext_tocanvas, METH_VARARGS,"Send message to canvas" },
@@ -56,6 +57,7 @@ const char *pyext::pyext_doc =
"_isthreaded(self): Query whether threading is enabled\n"
;
+/*
PyObject* pyext::pyext__init__(PyObject *,PyObject *args)
{
// post("pyext.__init__ called");
@@ -71,6 +73,7 @@ PyObject* pyext::pyext__del__(PyObject *,PyObject *args)
Py_INCREF(Py_None);
return Py_None;
}
+*/
PyObject* pyext::pyext_setattr(PyObject *,PyObject *args)
{
@@ -82,13 +85,15 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args)
}
bool handled = false;
+
+/*
if(PyString_Check(name)) {
char* sname = PyString_AsString(name);
if (sname) {
// post("pyext::setattr %s",sname);
}
}
-
+*/
if(!handled) {
if(PyInstance_Check(self))
PyDict_SetItem(((PyInstanceObject *)self)->in_dict, name,val);
@@ -109,8 +114,8 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args)
}
if(PyString_Check(name)) {
- char* sname = PyString_AsString(name);
- if (sname) {
+ char* sname = PyString_AS_STRING(name);
+ if(sname) {
if(!strcmp(sname,"_shouldexit")) {
pyext *ext = GetThis(self);
if(ext)
@@ -122,8 +127,7 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args)
if(!ret) {
#if PY_VERSION_HEX >= 0x02020000
- // \todo borrowed or new???
- ret = PyObject_GenericGetAttr(self,name);
+ ret = PyObject_GenericGetAttr(self,name); // new reference (?)
#else
if(PyInstance_Check(self))
// borrowed reference
@@ -141,22 +145,24 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args)
// should always be a tuple!
FLEXT_ASSERT(PyTuple_Check(args));
+ int sz = PyTuple_GET_SIZE(args);
+
// borrowed references!
- PyObject *self = PyTuple_GetItem(args,0);
- PyObject *outl = PyTuple_GetItem(args,1);
+ PyObject *self,*outl;
+
if(
- self && PyInstance_Check(self) &&
- outl && PyInt_Check(outl)
+ 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);
- int sz = PyTuple_Size(args);
PyObject *val;
bool tp =
sz == 3 &&
PySequence_Check(
- val = PyTuple_GetItem(args,2) // borrow reference
+ val = PyTuple_GET_ITEM(args,2) // borrow reference
);
if(!tp)
@@ -255,18 +261,22 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args)
{
FLEXT_ASSERT(PyTuple_Check(args));
+ int sz = PyTuple_GET_SIZE(args);
+
bool ok = false;
- PyObject *self = PyTuple_GetItem(args,0); // borrowed ref
- if(self && PyInstance_Check(self)) {
+ PyObject *self; // borrowed ref
+ if(
+ sz >= 1 &&
+ (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self)
+ ) {
pyext *ext = GetThis(self);
- int sz = PySequence_Size(args);
PyObject *val;
bool tp =
sz == 2 &&
PySequence_Check(
- val = PyTuple_GetItem(args,1) // borrowed ref
+ val = PyTuple_GET_ITEM(args,1) // borrowed ref
);
if(!tp)
diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp
index 636435b3..33200c8b 100644
--- a/externals/grill/py/source/main.cpp
+++ b/externals/grill/py/source/main.cpp
@@ -56,6 +56,8 @@ void py::FreeThreadState()
#endif
+void initsymbol();
+
void py::lib_setup()
{
post("");
@@ -76,8 +78,7 @@ void py::lib_setup()
Py_Initialize();
#ifdef FLEXT_DEBUG
-// Py_DebugFlag = 1;
- Py_VerboseFlag = 1;
+// Py_VerboseFlag = 1;
#endif
#ifdef FLEXT_THREADS
@@ -99,6 +100,18 @@ void py::lib_setup()
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;
py_out = Py_InitModule("stdout", StdOut_Methods);
@@ -124,6 +137,16 @@ PyObject *py::module_obj = NULL;
PyObject *py::module_dict = NULL;
+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),
detach(0),shouldexit(false),thrcount(0),
@@ -150,7 +173,7 @@ py::~py()
// Wait forever
post("%s - Waiting for thread termination!",thisName());
- while(thrcount) Sleep(0.2f);
+ while(thrcount) Sleep(0.01f);
post("%s - Okay, all threads have terminated",thisName());
}
@@ -198,7 +221,7 @@ void py::m__doc(PyObject *obj)
PyObject *docf = PyDict_GetItemString(obj,"__doc__"); // borrowed!!!
if(docf && PyString_Check(docf)) {
post("");
- const char *s = PyString_AsString(docf);
+ const char *s = PyString_AS_STRING(docf);
// FIX: Python doc strings can easily be larger than 1k characters
// -> split into separate lines
@@ -226,6 +249,10 @@ void py::m__doc(PyObject *obj)
}
}
+void py::m_click()
+{
+ // this should once open the editor....
+}
void py::SetArgs(int argc,const t_atom *argv)
{
@@ -251,8 +278,7 @@ void py::ImportModule(const char *name)
if(!name) return;
module = PyImport_ImportModule((char *)name); // increases module_obj ref count by one
- if (!module) {
-
+ if(!module) {
PyErr_Print();
dict = NULL;
}
@@ -264,7 +290,7 @@ void py::UnimportModule()
{
if(!module) return;
- assert(dict && module_obj && module_dict);
+ FLEXT_ASSERT(dict && module_obj && module_dict);
Py_DECREF(module);
@@ -343,17 +369,12 @@ void py::AddToPath(const char *dir)
if(dir && *dir) {
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);
- }
+ PyObject *ps = PyString_FromString(dir);
+ if(!PySequence_Contains(pobj,ps))
+ PyList_Append(pobj,ps); // makes new reference
+ Py_DECREF(ps);
}
- PySys_SetObject("path",pobj);
+ PySys_SetObject("path",pobj); // steals reference to pobj
}
}
@@ -378,9 +399,10 @@ PyObject* py::StdOut_Write(PyObject* self, PyObject* args)
// should always be a tuple
FLEXT_ASSERT(PyTuple_Check(args));
- int sz = PyTuple_Size(args);
+ const int sz = PyTuple_GET_SIZE(args);
+
for(int i = 0; i < sz; ++i) {
- PyObject *val = PyTuple_GetItem(args,i); // borrowed reference
+ PyObject *val = PyTuple_GET_ITEM(args,i); // borrowed reference
PyObject *str = PyObject_Str(val); // new reference
char *cstr = PyString_AS_STRING(str);
char *lf = strchr(cstr,'\n');
diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h
index 03b67e1c..ef9a16c9 100644
--- a/externals/grill/py/source/main.h
+++ b/externals/grill/py/source/main.h
@@ -11,23 +11,13 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#ifndef __MAIN_H
#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
+#include "pyprefix.h"
+#include "pysymbol.h"
#if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX
#include <unistd.h>
#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"
@@ -61,7 +51,7 @@ protected:
class py:
public flext_base
{
- FLEXT_HEADER(py,flext_base)
+ FLEXT_HEADER_S(py,flext_base,Setup)
public:
py();
@@ -190,8 +180,12 @@ public:
static PyObject* StdOut_Write(PyObject* Self, PyObject* Args);
protected:
- // callbacks
+ virtual void m_click();
+
+ static void Setup(t_classid c);
+
+ // callbacks
FLEXT_ATTRVAR_I(detach)
FLEXT_ATTRVAR_B(respond)
FLEXT_CALLBACK_V(m_stop)
diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp
index 88e3290a..cf4dca88 100644
--- a/externals/grill/py/source/modmeth.cpp
+++ b/externals/grill/py/source/modmeth.cpp
@@ -107,16 +107,19 @@ PyObject *py::py_send(PyObject *,PyObject *args)
// should always be a tuple
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);
+ 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;
bool tp =
sz == 2 &&
PySequence_Check(
- val = PyTuple_GetItem(args,1) // borrowed ref
+ val = PyTuple_GET_ITEM(args,1) // borrowed ref
);
if(!tp)
@@ -168,12 +171,14 @@ PyObject *py::py_getvalue(PyObject *self,PyObject *args)
{
FLEXT_ASSERT(PyTuple_Check(args));
+ const int sz = PyTuple_GET_SIZE(args);
+ const t_symbol *sym;
PyObject *ret;
- PyObject *name = PyTuple_GetItem(args,0); // borrowed reference
-
- if(name && PyString_Check(name)) {
- const t_symbol *sym = MakeSymbol(PyString_AsString(name));
+ if(
+ sz == 1 &&
+ (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL
+ ) {
float f;
if(value_getfloat(const_cast<t_symbol *>(sym),&f)) {
post("py/pyext - Could not get value '%s'",GetString(sym));
@@ -193,10 +198,15 @@ PyObject *py::py_setvalue(PyObject *self,PyObject *args)
{
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));
+ 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);
if(value_setfloat(const_cast<t_symbol *>(sym),f))
diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp
index 3bad1890..68f805b8 100644
--- a/externals/grill/py/source/py.cpp
+++ b/externals/grill/py/source/py.cpp
@@ -81,19 +81,14 @@ FLEXT_LIB_V("py",pyobj)
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,"reload.",m_reload);
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_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);
FLEXT_CADDMETHOD(c,1,m_py_list);
diff --git a/externals/grill/py/source/pyargs.cpp b/externals/grill/py/source/pyargs.cpp
index 90686a90..1b549160 100644
--- a/externals/grill/py/source/pyargs.cpp
+++ b/externals/grill/py/source/pyargs.cpp
@@ -12,7 +12,8 @@ WARRANTIES, see the file, "license.txt," in this distribution.
static PyObject *MakePyAtom(const t_atom &at)
{
- if(flext::IsSymbol(at)) return PyString_FromString(flext::GetString(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)) {
// if a number can be an integer... let at be an integer!
@@ -45,24 +46,16 @@ PyObject *py::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet
int pix = 0;
- if(inlet >= 0) {
- PyObject *pValue = PyInt_FromLong(inlet);
-
- // reference stolen:
- PyTuple_SetItem(pArgs, pix++, pValue);
- }
+ if(inlet >= 0)
+ PyTuple_SetItem(pArgs, pix++, PyInt_FromLong(inlet));
int ix;
PyObject *tmp;
if(!withself || argc < (any?1:2)) tmp = pArgs,ix = pix;
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);
- }
+ if(any)
+ PyTuple_SET_ITEM(tmp, ix++, pySymbol_FromSymbol(s));
for(int i = 0; i < argc; ++i) {
PyObject *pValue = MakePyAtom(argv[i]);
@@ -72,11 +65,11 @@ PyObject *py::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet
}
/* pValue reference stolen here: */
- PyTuple_SetItem(tmp, ix++, pValue);
+ PyTuple_SET_ITEM(tmp, ix++, pValue);
}
if(tmp != pArgs) {
- PyTuple_SetItem(pArgs, pix++, tmp);
+ PyTuple_SET_ITEM(pArgs, pix++, tmp);
#if PY_VERSION_HEX >= 0x02020000
_PyTuple_Resize(&pArgs,pix);
#else
@@ -126,7 +119,8 @@ flext::AtomList *py::GetPyArgs(PyObject *pValue,PyObject **self)
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(PyString_Check(arg)) SetString((*ret)[ix],PyString_AsString(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_ !!!
Py_INCREF(arg);
@@ -136,7 +130,7 @@ flext::AtomList *py::GetPyArgs(PyObject *pValue,PyObject **self)
PyObject *tp = PyObject_Type(arg);
PyObject *stp = tp?PyObject_Str(tp):NULL;
char *tmp = "";
- if(stp) tmp = PyString_AsString(stp);
+ if(stp) tmp = PyString_AS_STRING(stp);
post("py/pyext: Could not convert argument %s",tmp);
Py_XDECREF(stp);
Py_XDECREF(tp);
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp
index fed6c89e..4acafd60 100644
--- a/externals/grill/py/source/pyext.cpp
+++ b/externals/grill/py/source/pyext.cpp
@@ -20,20 +20,13 @@ void pyext::Setup(t_classid c)
{
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,"reload.",m_reload);
FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_);
-
- FLEXT_CADDATTR_VAR(c,"args",args,ms_args);
+ FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
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_CADDATTR_VAR(c,"args",args,ms_args);
FLEXT_CADDMETHOD_(c,0,"get",m_get);
FLEXT_CADDMETHOD_(c,0,"set",m_set);
@@ -172,58 +165,8 @@ pyext::pyext(int argc,const t_atom *argv):
if(methname) {
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();
- }
- }
+ if(pyobj)
+ InitInOut(inlets,outlets);
}
else
inlets = outlets = 0;
@@ -245,12 +188,7 @@ pyext::~pyext()
{
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
- }
+ DoExit();
Unregister("_pyext");
UnimportModule();
@@ -269,8 +207,8 @@ bool pyext::DoInit()
PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref
if(init) {
- if(PyCallable_Check(init)) {
- PyObject *res = PyEval_CallObject(init,pargs);
+ if(PyMethod_Check(init)) {
+ PyObject *res = PyObject_CallObject(init,pargs);
if(!res)
PyErr_Print();
else
@@ -283,6 +221,86 @@ bool pyext::DoInit()
return true;
}
+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()
{
// pyobj should already have been decref'd / cleared before getting here!!
@@ -311,8 +329,7 @@ bool pyext::MakeInstance()
void pyext::Reload()
{
- ClearBinding();
- Py_XDECREF(pyobj);
+ DoExit();
// by here, the Python class destructor should have been called!
@@ -320,6 +337,12 @@ void pyext::Reload()
ReloadModule();
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());
}
diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h
index 45ba866d..f94b2f19 100644
--- a/externals/grill/py/source/pyext.h
+++ b/externals/grill/py/source/pyext.h
@@ -70,6 +70,8 @@ private:
void ClearBinding();
bool MakeInstance();
bool DoInit();
+ void DoExit();
+ void InitInOut(int &inlets,int &outlets);
AtomList args;
diff --git a/externals/grill/py/source/pyprefix.h b/externals/grill/py/source/pyprefix.h
new file mode 100644
index 00000000..fcce64a1
--- /dev/null
+++ b/externals/grill/py/source/pyprefix.h
@@ -0,0 +1,27 @@
+/*
+
+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
diff --git a/externals/grill/py/source/pysymbol.cpp b/externals/grill/py/source/pysymbol.cpp
new file mode 100644
index 00000000..176f9895
--- /dev/null
+++ b/externals/grill/py/source/pysymbol.cpp
@@ -0,0 +1,168 @@
+/*
+
+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;
+}
diff --git a/externals/grill/py/source/pysymbol.h b/externals/grill/py/source/pysymbol.h
new file mode 100644
index 00000000..bf06437d
--- /dev/null
+++ b/externals/grill/py/source/pysymbol.h
@@ -0,0 +1,57 @@
+/*
+
+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);
+}
+