diff options
-rw-r--r-- | externals/grill/py/py.vcproj | 425 | ||||
-rw-r--r-- | externals/grill/py/readme.txt | 7 | ||||
-rw-r--r-- | externals/grill/py/scripts/sendrecv.py | 9 | ||||
-rw-r--r-- | externals/grill/py/source/bound.cpp | 151 | ||||
-rw-r--r-- | externals/grill/py/source/clmeth.cpp | 21 | ||||
-rw-r--r-- | externals/grill/py/source/main.cpp | 57 | ||||
-rw-r--r-- | externals/grill/py/source/main.h | 27 | ||||
-rw-r--r-- | externals/grill/py/source/modmeth.cpp | 22 | ||||
-rw-r--r-- | externals/grill/py/source/py.cpp | 2 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.cpp | 53 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.h | 34 |
11 files changed, 595 insertions, 213 deletions
diff --git a/externals/grill/py/py.vcproj b/externals/grill/py/py.vcproj index dad3f95d..51ae2865 100644 --- a/externals/grill/py/py.vcproj +++ b/externals/grill/py/py.vcproj @@ -42,7 +42,7 @@ OutputFile=".\pd-msvc\d/py.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="c:/programme/audio/pd/bin;"..\flext\pd-msvc"" + AdditionalLibraryDirectories="c:/programme/audio/pd/bin;"..\flext\pd-msvc";"F:\prog\packs\Python-2.3.2\PCbuild"" GenerateDebugInformation="TRUE" ProgramDatabaseFile=".\pd-msvc\d/py.pdb" ImportLibrary=".\pd-msvc\d/py.lib" @@ -87,8 +87,8 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="c:\programme\audio\pd\src,f:\prog\max\flext\source,C:\Programme\prog\Python22\include" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=2;FLEXT_THREADS" + AdditionalIncludeDirectories="c:\programme\audio\pd\src;f:\prog\max\flext\source;C:\Programme\prog\Python23\include" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=2;FLEXT_THREADS;_USEFLEXTBINDING" BasicRuntimeChecks="3" RuntimeLibrary="1" RuntimeTypeInfo="TRUE" @@ -106,7 +106,7 @@ OutputFile=".\pd-msvc\td/py.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="c:/programme/audio/pd/bin,..\flext\pd-msvc,f:\prog\packs\Python-2.2.1\PCbuild" + AdditionalLibraryDirectories="c:/programme/audio/pd/bin;"..\flext\pd-msvc";"f:\prog\packs\Python-2.3.2\PCbuild"" GenerateDebugInformation="TRUE" ProgramDatabaseFile=".\pd-msvc\td/py.pdb" ImportLibrary=".\pd-msvc\td/py.lib" @@ -228,7 +228,7 @@ Name="VCCustomBuildTool"/> <Tool Name="VCLinkerTool" - AdditionalDependencies="pd.lib python23.lib" + AdditionalDependencies="pd.lib" OutputFile=".\pd-msvc\r/py.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" @@ -276,7 +276,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="f:\prog\pd\pd-cvs\src;f:\prog\packs\pthreads,f:\prog\max\flext\source,C:\Programme\prog\Python22\include" + AdditionalIncludeDirectories=""f:\prog\pd\pd-cvs\src";f:\prog\packs\pthreads;f:\prog\max\flext\source;C:\Programme\prog\Python23\include" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=2;FLEXT_SHARED" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -295,7 +295,7 @@ OutputFile="$(outdir)/py.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="f:\prog\pd\pd-cvs/bin,f:\prog\packs\pthreads;f:\prog\packs\Python-2.2.1\PCbuild" + AdditionalLibraryDirectories=""f:\prog\pd\pd-cvs/bin";f:\prog\packs\pthreads;"f:\prog\packs\Python-2.3.2\PCbuild"" GenerateDebugInformation="TRUE" ProgramDatabaseFile=".\pd-msvc\td/py.pdb" ImportLibrary=".\pd-msvc\td/py.lib" @@ -392,6 +392,201 @@ <Tool Name="VCAuxiliaryManagedWrapperGeneratorTool"/> </Configuration> + <Configuration + Name="Max Shared Debug|Win32" + OutputDirectory=".\max-msvc\sd" + IntermediateDirectory=".\max-msvc\sd" + ConfigurationType="2" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes";"F:\prog\audio\MaxWinSDK\c74support\max-includes";f:\prog\packs\pthreads;f:\prog\max\flext\source;C:\Programme\prog\Python23\include" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=1;FLEXT_SHARED" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="2" + BrowseInformation="1" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="maxapi.lib maxext.lib maxaudio.lib pthreadVC.lib" + OutputFile="$(outdir)/py.mxe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + AdditionalLibraryDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes\win-includes\debug";"F:\prog\audio\MaxWinSDK\c74support\max-includes\win-includes\debug";f:\prog\packs\pthreads;"f:\prog\packs\Python-2.3.2\PCbuild"" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(intdir)/py.pdb" + ImportLibrary="$(intdir)/py.lib" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\pd-msvc\td/py.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="3079"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Max Threaded Debug|Win32" + OutputDirectory=".\max-msvc\td" + IntermediateDirectory=".\max-msvc\td" + ConfigurationType="2" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes";"F:\prog\audio\MaxWinSDK\c74support\max-includes";f:\prog\packs\pthreads;f:\prog\max\flext\source;C:\Programme\prog\Python23\include" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=1;FLEXT_THREADS" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="2" + BrowseInformation="1" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="maxapi.lib maxext.lib maxaudio.lib pthreadVC.lib" + OutputFile="$(outdir)/py.mxe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + AdditionalLibraryDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes\win-includes\debug";"F:\prog\audio\MaxWinSDK\c74support\max-includes\win-includes\debug";f:\prog\packs\pthreads;"f:\prog\packs\Python-2.3.2\PCbuild"" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(intdir)/py.pdb" + ImportLibrary="$(intdir)/py.lib" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\pd-msvc\td/py.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="3079"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Max Threaded Release|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="3" + GlobalOptimizations="FALSE" + FavorSizeOrSpeed="1" + AdditionalIncludeDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes";"F:\prog\audio\MaxWinSDK\c74support\max-includes";f:\prog\packs\pthreads;f:\prog\max\flext\source;C:\Programme\prog\Python23\include" + PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;FLEXT_SYS=1;FLEXT_THREADS" + BasicRuntimeChecks="3" + RuntimeLibrary="0" + EnableEnhancedInstructionSet="1" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="2" + BrowseInformation="1" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="0" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="maxapi.lib maxext.lib maxaudio.lib pthreadVC.lib" + OutputFile="./max-msvc/py.mxe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + AdditionalLibraryDirectories=""F:\prog\audio\MaxWinSDK\c74support\msp-includes\win-includes\release";"F:\prog\audio\MaxWinSDK\c74support\max-includes\win-includes\release";f:\prog\packs\pthreads;C:\Programme\prog\Python23\libs" + GenerateDebugInformation="FALSE" + ProgramDatabaseFile="$(intdir)/py.pdb" + ImportLibrary="$(intdir)/py.lib" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\pd-msvc\td/py.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="3079"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> </Configurations> <References> </References> @@ -489,6 +684,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\clmeth.cpp"> @@ -541,6 +763,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\main.cpp"> @@ -593,6 +842,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\main.h"> @@ -648,6 +924,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\py.cpp"> @@ -700,6 +1003,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\pyargs.cpp"> @@ -752,6 +1082,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\pyext.cpp"> @@ -804,6 +1161,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> <File RelativePath="source\pyext.h"> @@ -859,6 +1243,33 @@ Optimization="2" AdditionalIncludeDirectories=""/> </FileConfiguration> + <FileConfiguration + Name="Max Shared Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> + <FileConfiguration + Name="Max Threaded Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + BasicRuntimeChecks="3" + BrowseInformation="1"/> + </FileConfiguration> </File> </Files> <Globals> diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt index df8dd360..88c1ec00 100644 --- a/externals/grill/py/readme.txt +++ b/externals/grill/py/readme.txt @@ -49,7 +49,7 @@ Therefore, some help patches may not be functional. ---------------------------------------------------------------------------- The py/pyext package should run with Python version >= 2.1. -It has been thoroughly tested with version 2.2 +It has been thoroughly tested with version 2.2 and 2.3 The package should at least compile (and is tested) with the following compilers: @@ -79,6 +79,10 @@ Version history: 0.1.2: - CHANGE: updates for flext 0.4.1 - method registering within class scope - fixed bugs in bound.cpp (object_free calls) +- bug fixed for threaded methods along with flext bug fix. +- map Python threads to system threads +- shut down Python appropriately +- use flext timer and bind functionality 0.1.1: - CHANGE: updates for flext 0.4.0 @@ -120,6 +124,5 @@ tests: - check for python threading support bugs: -- the python interpreter can't be unloaded due to some bug at re-initialization - named (keyword) arguments are not supported diff --git a/externals/grill/py/scripts/sendrecv.py b/externals/grill/py/scripts/sendrecv.py index 2d0eb9e6..0488359b 100644 --- a/externals/grill/py/scripts/sendrecv.py +++ b/externals/grill/py/scripts/sendrecv.py @@ -77,7 +77,7 @@ class ex1(pyext._class): # you can but you don't need to # unbinding is automatically done at destruction - # you can also comment the _unbind lines + # you can also comment out the _unbind lines self._unbind(self.recvname,self.recv) self._unbind(self.recvname,recv_gl) @@ -118,7 +118,7 @@ class ex2(pyext._class): ################################################################# -from math import sin,cos,pi +from math import pi from cmath import exp from random import random,randint @@ -134,8 +134,9 @@ class ex3(pyext._class): """Class constructor""" # called scripting method should run on its own thread - self._detach(1) - + if self._isthreaded(): + print "Threading is on" + self._detach(1) def bang_1(self): """Do some scripting - PD only!""" diff --git a/externals/grill/py/source/bound.cpp b/externals/grill/py/source/bound.cpp index e8e2599f..c0e8c35a 100644 --- a/externals/grill/py/source/bound.cpp +++ b/externals/grill/py/source/bound.cpp @@ -11,44 +11,32 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pyext.h" #include "flinternal.h" -#ifndef USEFLEXTBINDING -t_class *pyext::px_class; -pyext::py_proxy *pyext::px_head,*pyext::px_tail; +struct bounddata +{ + PyObject *self; + std::set<PyObject *> funcs; +}; -void pyext::py_proxy::px_method(py_proxy *obj,const t_symbol *s,int argc,const t_atom *argv) -{ - PY_LOCK - - PyObject *args = MakePyArgs(s,AtomList(argc,argv),-1,obj->self != NULL); - PyObject *ret = PyObject_CallObject(obj->func,args); - if(!ret) { - PyErr_Print(); - } - Py_XDECREF(ret); - - PY_UNLOCK -} - -#else -struct bounddata { PyObject *self,*func; }; - -bool pyext::boundmeth(flext_base *,const t_symbol *sym,int argc,const t_atom *argv,void *data) +bool pyext::boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data) { bounddata *obj = (bounddata *)data; PY_LOCK PyObject *args = MakePyArgs(sym,AtomList(argc,argv),-1,obj->self != NULL); - PyObject *ret = PyObject_CallObject(obj->func,args); - if(!ret) { - PyErr_Print(); - } - Py_XDECREF(ret); + + // call all functions bound by this symbol + for(std::set<PyObject *>::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) { + PyObject *ret = PyObject_CallObject(*it,args); + if(!ret) { + PyErr_Print(); + } + Py_XDECREF(ret); + } PY_UNLOCK return true; } -#endif PyObject *pyext::pyext_bind(PyObject *,PyObject *args) { @@ -72,25 +60,22 @@ PyObject *pyext::pyext_bind(PyObject *,PyObject *args) meth = PyObject_GetAttr(self,no); Py_DECREF(no); } -#ifndef USEFLEXTBINDING - py_proxy *px = (py_proxy *)object_new(px_class); - px->init(recv,self,meth); - - // add it to the list - if(px_tail) px_tail->nxt = px; - else px_head = px; - px_tail = px; - - // Do bind - pd_bind(&px->obj.ob_pd,(t_symbol *)recv); -#else - bounddata *data = new bounddata; - data->self = self; - data->func = meth; - GetThis(self)->BindMethod(recv,boundmeth,data); -#endif - - Py_INCREF(self); // self is borrowed reference + + 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 + } } Py_INCREF(Py_None); @@ -114,42 +99,21 @@ PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) Py_DECREF(no); } -#ifndef USEFLEXTBINDING - // search proxy object - py_proxy *pp = NULL,*px = px_head; - while(px) { - py_proxy *pn = px->nxt; - if(recv == px->name && self == px->self && meth == px->func) { - if(pp) - pp->nxt = pn; - else - px_head = pn; - if(!pn) px_tail = pp; - break; - } - else pp = px; - px = pn; - } - - // do unbind - if(px) { - pd_unbind(&px->obj.ob_pd,(t_symbol *)recv); - object_free(&px->obj); - - Py_DECREF(self); - if(PyMethod_Check(meth)) Py_DECREF(meth); - } -#else void *data = NULL; if(GetThis(self)->UnbindMethod(recv,boundmeth,&data)) { - bounddata *bdt = (bounddata *)data; - if(bdt) { - Py_DECREF(bdt->self); - if(PyMethod_Check(bdt->func)) Py_DECREF(bdt->func); - if(data) delete bdt; + 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; } } -#endif } Py_INCREF(Py_None); @@ -159,28 +123,6 @@ PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) V pyext::ClearBinding() { -#ifndef USEFLEXTBINDING - // search proxy object - py_proxy *pp = NULL,*px = px_head; - while(px) { - py_proxy *pn = px->nxt; - if(px->self == pyobj) { - if(pp) - pp->nxt = pn; - else - px_head = pn; - if(!pn) px_tail = pp; - - Py_DECREF(px->self); - if(PyMethod_Check(px->func)) Py_DECREF(px->func); - - pd_unbind(&px->obj.ob_pd,(t_symbol *)px->name); - object_free(&px->obj); - } - else pp = px; - px = pn; - } -#else void *data = NULL; const t_symbol *sym = NULL; @@ -188,12 +130,13 @@ V pyext::ClearBinding() while(GetThis(pyobj)->UnbindMethod(sym,NULL,&data)) { bounddata *bdt = (bounddata *)data; if(bdt) { + for(std::set<PyObject *>::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(PyMethod_Check(bdt->func)) Py_DECREF(bdt->func); if(data) delete bdt; } } -#endif } - - diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index cf2b6842..f800aa7d 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -17,7 +17,9 @@ PyMethodDef pyext::meth_tbl[] = {"__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" }, +#endif { "_bind", pyext::pyext_bind, METH_VARARGS,"Bind function to a receiving symbol" }, { "_unbind", pyext::pyext_unbind, METH_VARARGS,"Unbind function from a receiving symbol" }, @@ -25,6 +27,7 @@ PyMethodDef pyext::meth_tbl[] = { "_detach", pyext::pyext_detach, METH_VARARGS,"Set detach flag for called methods" }, { "_stop", pyext::pyext_stop, METH_VARARGS,"Stop running threads" }, #endif + { "_isthreaded", pyext::pyext_isthreaded, METH_O,"Query whether threading is enabled" }, {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -221,6 +224,19 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) #endif +//! Query whether threading is enabled +PyObject *pyext::pyext_isthreaded(PyObject *,PyObject *) +{ + return Py_BuildValue("i", +#ifdef FLEXT_THREADED + 1 +#else + 0 +#endif + ); +} + +#if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) { @@ -244,11 +260,7 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) t_glist *gl = ext->thisCanvas(); //canvas_getcurrent(); t_class **cl = (t_pd *)gl; if(cl) { -#if FLEXT_SYS == FLEXT_SYS_PD pd_forwardmess(cl,lst->Count(),lst->Atoms()); -#else -#pragma message ("Send is not implemented") -#endif } #ifdef FLEXT_DEBUG else @@ -269,6 +281,7 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) Py_INCREF(Py_None); return Py_None; } +#endif diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp index 21e78f05..03e2aab7 100644 --- a/externals/grill/py/source/main.cpp +++ b/externals/grill/py/source/main.cpp @@ -13,7 +13,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. V py::lib_setup() { post(""); - post("py/pyext %s - python script objects, (C)2002 Thomas Grill",PY__VERSION); + post("py/pyext %s - python script objects, (C)2002,2003 Thomas Grill",PY__VERSION); post(""); FLEXT_SETUP(pyobj); @@ -25,7 +25,7 @@ V py::lib_setup() FLEXT_LIB_SETUP(py,py::lib_setup) PyInterpreterState *py::pystate = NULL; - +std::map<flext::thrid_t,PyThreadState *> py::pythrmap; I py::pyref = 0; PyObject *py::module_obj = NULL; @@ -35,28 +35,35 @@ PyObject *py::module_dict = NULL; py::py(): module(NULL), detach(false),shouldexit(false),thrcount(0), - clk(NULL),stoptick(0) + stoptick(0) { Lock(); - // under Max/MSP: doesn't survive next line..... + // under Max/MSP @ OS9: doesn't survive next line..... if(!(pyref++)) { Py_Initialize(); #ifdef FLEXT_THREADS + // enable thread support and acquire the global thread lock PyEval_InitThreads(); - pystate = PyThreadState_Get()->interp; - #endif - // register/initialize pyext module only once! + // get thread state + PyThreadState *pythrmain = PyThreadState_Get(); + // get main interpreter state + pystate = pythrmain->interp; + + // release global lock + PyEval_ReleaseLock(); + + // add thread state of main thread to map + pythrmap[GetThreadId()] = pythrmain; + #endif + + // register/initialize pyext module only once! module_obj = Py_InitModule(PYEXT_MODULE, func_tbl); module_dict = PyModule_GetDict(module_obj); PyModule_AddStringConstant(module_obj,"__doc__",(C *)py_doc); - - #ifdef FLEXT_THREADS - pythrmain = PyEval_SaveThread(); - #endif } else { PY_LOCK @@ -67,7 +74,7 @@ py::py(): Unlock(); - clk = clock_new(this,(t_method)tick); + FLEXT_ADDTIMER(stoptmr,tick); } py::~py() @@ -84,31 +91,33 @@ py::~py() post("%s - Okay, all threads have terminated",thisName()); } -/* - // don't unregister - Lock(); if(!(--pyref)) { - Py_DECREF(module_obj); + // no more py/pyext objects left... shut down Python + module_obj = NULL; - Py_DECREF(module_dict); module_dict = NULL; Py_XDECREF(module); -// delete modules; modules = NULL; - - PyEval_AcquireThread(pythrmain); - PyThreadState *new_state = PyThreadState_New(pystate); // must have lock - PyThreadState *prev_state = PyThreadState_Swap(new_state); + PyEval_AcquireLock(); + PyThreadState_Swap(pythrmap[GetThreadId()]); +#ifdef FLEXT_DEBUG + // need not necessarily do that.... Py_Finalize(); +#endif + + // reset thread state map + pythrmap.clear(); } + else { + Py_DECREF(module_obj); + Py_DECREF(module_dict); + } Unlock(); -*/ - if(clk) clock_free(clk); } diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index ef28b7ec..fd25e1f1 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -13,13 +13,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include <flext.h> #include <Python.h> +#include <map> #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX #include <unistd.h> #endif -#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 403) -#error You need at least flext version 0.4.3 +#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) +#error You need at least flext version 0.5.0 #endif #define PY__VERSION "0.1.2pre" @@ -103,14 +104,14 @@ protected: BL detach,shouldexit; I thrcount; - t_clock *clk; I stoptick; + Timer stoptmr; - static V tick(py *obj); + V tick(V *); public: static PyInterpreterState *pystate; - PyThreadState *pythrmain; + static std::map<flext::thrid_t,PyThreadState *> pythrmap; #ifdef FLEXT_THREADS ThrMutex mutex; @@ -127,19 +128,23 @@ protected: FLEXT_CALLBACK_B(m_detach) FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_doc) + FLEXT_CALLBACK_T(tick) }; #ifdef FLEXT_THREADS + #define PY_LOCK \ { \ - PyThreadState *thrst = PyThreadState_New(pystate); \ - PyEval_AcquireThread(thrst); + PyEval_AcquireLock(); \ + PyThreadState *__st = pythrmap[GetThreadId()]; \ + FLEXT_ASSERT(__st != NULL); \ + PyThreadState *__oldst = PyThreadState_Swap(__st); #define PY_UNLOCK \ - PyThreadState_Clear(thrst); /* must have lock */ \ - PyEval_ReleaseThread(thrst); \ - PyThreadState_Delete(thrst); /* needn't have lock */ \ - } + PyThreadState_Swap(__oldst); \ + PyEval_ReleaseLock(); \ + } + #else #define PY_LOCK #define PY_UNLOCK diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index 83e8a7b6..b376a4fb 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -43,27 +43,27 @@ const C *py::py_doc = -V py::tick(py *th) +V py::tick(V *) { - th->Lock(); + Lock(); - if(!th->thrcount) { + if(!thrcount) { // all threads have stopped - th->shouldexit = false; - th->stoptick = 0; + shouldexit = false; + stoptick = 0; } else { // still active threads - if(!--th->stoptick) { - post("%s - Threads couldn't be stopped entirely - %i remaining",th->thisName(),th->thrcount); - th->shouldexit = false; + if(!--stoptick) { + post("%s - Threads couldn't be stopped entirely - %i remaining",thisName(),thrcount); + shouldexit = false; } else // continue waiting - clock_delay(th->clk,PY_STOP_TICK); + stoptmr.Delay(PY_STOP_TICK/1000.); } - th->Unlock(); + Unlock(); } V py::m_stop(int argc,const t_atom *argv) @@ -82,7 +82,7 @@ V py::m_stop(int argc,const t_atom *argv) else stoptick = ticks; shouldexit = true; - clock_delay(clk,PY_STOP_TICK); + stoptmr.Delay(PY_STOP_TICK/1000.); Unlock(); } diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index 57bf063d..1955c250 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -73,7 +73,7 @@ private: FLEXT_LIB_V("py",pyobj) -void pyobj::Setup(t_class *c) +void pyobj::Setup(t_classid c) { FLEXT_CADDBANG(c,0,m_bang); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index 39981beb..14d0f7b6 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -16,13 +16,6 @@ FLEXT_LIB_V("pyext",pyext) V pyext::Setup(t_classid c) { -#ifndef USEFLEXTBINDING - px_head = px_tail = NULL; - - px_class = class_new(gensym("pyext proxy"),NULL,NULL,sizeof(py_proxy),CLASS_PD|CLASS_NOINLET, A_NULL); - ::add_anything(px_class,py_proxy::px_method); // for other inlets -#endif - FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); FLEXT_CADDMETHOD_(c,0,"doc",m_doc); @@ -116,6 +109,7 @@ pyext::pyext(I argc,const t_atom *argv): post("%s - script name argument is invalid",thisName()); else { SetArgs(0,NULL); + ImportModule(GetString(argv[0])); } } @@ -192,14 +186,12 @@ pyext::~pyext() Py_XDECREF(class_obj); Py_XDECREF(class_dict); -/* - // Don't unregister if(!--pyextref) { class_obj = NULL; class_dict = NULL; } -*/ + PY_UNLOCK } @@ -358,9 +350,6 @@ PyObject *pyext::call(const C *meth,I inlet,const t_symbol *s,I argc,const t_ato #else PyErr_Clear(); #endif - else { -// Py_DECREF(pres); - } Py_DECREF(pargs); } @@ -379,9 +368,41 @@ V pyext::work_wrapper(V *data) else #endif { - work_data *w = (work_data *)data; - work(w->n,w->Header(),w->Count(),w->Atoms()); - delete w; + // --- make new Python thread --- + // get the global lock + PyEval_AcquireLock(); + // get a reference to the PyInterpreterState + // create a thread state object for this thread + PyThreadState *newthr = PyThreadState_New(pystate); + // free the lock + PyEval_ReleaseLock(); + // ----------------------------- + + // store new thread state + pythrmap[GetThreadId()] = newthr; + + { + // call worker + work_data *w = (work_data *)data; + work(w->n,w->Header(),w->Count(),w->Atoms()); + delete w; + } + + // delete mapped thread state + pythrmap.erase(GetThreadId()); + + // --- delete Python thread --- + // grab the lock + PyEval_AcquireLock(); + // swap my thread state out of the interpreter + PyThreadState_Swap(NULL); + // clear out any cruft from thread state object + PyThreadState_Clear(newthr); + // delete my thread state object + PyThreadState_Delete(newthr); + // release the lock + PyEval_ReleaseLock(); + // ----------------------------- } --thrcount; } diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h index 8f9a1b1b..9b37b6e4 100644 --- a/externals/grill/py/source/pyext.h +++ b/externals/grill/py/source/pyext.h @@ -27,13 +27,16 @@ public: static PyObject *pyext__del__(PyObject *,PyObject *args); static PyObject *pyext_outlet(PyObject *,PyObject *args); +#if FLEXT_SYS == FLEXT_SYS_PD static PyObject *pyext_tocanvas(PyObject *,PyObject *args); +#endif static PyObject *pyext_setattr(PyObject *,PyObject *args); static PyObject *pyext_getattr(PyObject *,PyObject *args); static PyObject *pyext_detach(PyObject *,PyObject *args); static PyObject *pyext_stop(PyObject *,PyObject *args); + static PyObject *pyext_isthreaded(PyObject *,PyObject *); I Inlets() const { return inlets; } I Outlets() const { return outlets; } @@ -68,36 +71,9 @@ private: static PyMethodDef attr_tbl[],meth_tbl[]; static const C *pyext_doc; - // -------- bound stuff ------------------ - -#ifndef USEFLEXTBINDING - static t_class *px_class; - - friend class py_proxy; - - class py_proxy // no virtual table! - { - public: - t_object obj; // MUST reside at memory offset 0 - PyObject *self,*func; - const t_symbol *name; - - py_proxy *nxt; - - void init(const t_symbol *n,PyObject *s,PyObject *f) { name = n,self = s,func = f,nxt = NULL; } -// bool cmp(PyObject *s,PyObject *f) const { return self == s && func == f; } -// void init(PyObject *s,char *f) { self = s,func = f,nxt = NULL; } -// bool cmp(PyObject *s,char *f) const { return self == s && func == f; } - static void px_method(py_proxy *c,const t_symbol *s,int argc,const t_atom *argv); - }; - static py_proxy *px_head,*px_tail; - - static PyObject *pyext_bind(PyObject *,PyObject *args); - static PyObject *pyext_unbind(PyObject *,PyObject *args); -#else + // -------- bind stuff ------------------ static PyObject *pyext_bind(PyObject *,PyObject *args); static PyObject *pyext_unbind(PyObject *,PyObject *args); -#endif // --------------------------- @@ -123,7 +99,7 @@ private: PyThreadState *pythr; private: - static bool boundmeth(flext_base *,const t_symbol *sym,int argc,const t_atom *argv,void *data); + static bool boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data); FLEXT_CALLBACK(m_reload) FLEXT_CALLBACK_V(m_reload_) |