diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2006-04-18 01:38:08 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2006-04-18 01:38:08 +0000 |
commit | ed0031b621c6cf8824a9a3e588426907244aeb7e (patch) | |
tree | a797d5ee35b65b43f970f331cdee940d7aaced32 | |
parent | 4e7353f45954a8a5d9aaa3dd40eed3f9f62c2062 (diff) |
implemented class-based method management
very fast native-to-managed transition
most of the logic transferred to the CLR side
svn path=/trunk/externals/clr/; revision=4931
-rwxr-xr-x | Counter/Counter.cs | 31 | ||||
-rw-r--r-- | Counter/Counter.csproj | 212 | ||||
-rwxr-xr-x | PureData/Atom.cs | 55 | ||||
-rw-r--r-- | PureData/DynamicMethod.cs | 101 | ||||
-rw-r--r-- | PureData/PureData.cs | 666 | ||||
-rw-r--r-- | PureData/PureData.csproj | 213 | ||||
-rwxr-xr-x | clr.cpp | 927 | ||||
-rw-r--r-- | test/test-help.pd | 53 | ||||
-rw-r--r-- | test/test.cs | 63 | ||||
-rw-r--r-- | test/test.csproj | 217 |
10 files changed, 1382 insertions, 1156 deletions
diff --git a/Counter/Counter.cs b/Counter/Counter.cs index 416cb3b..7b370d9 100755 --- a/Counter/Counter.cs +++ b/Counter/Counter.cs @@ -1,29 +1,32 @@ using System; +using PureData; /// <summary> /// Descrizione di riepilogo per Counter. /// </summary> public class Counter: - PureData.External + External { int i_count,i_down,i_up; float step; - public Counter(PureData.AtomList args) + public Counter() { } + + public Counter(Atom[] args) { - this.step = args.Count >= 3?(float)args[2]:1; + this.step = args.Length >= 3?(float)args[2]:1; - float f2 = args.Count >= 2?(float)args[1]:0; - float f1 = args.Count >= 1?(float)args[0]:0; + float f2 = args.Length >= 2?(float)args[1]:0; + float f1 = args.Length >= 1?(float)args[0]:0; - if(args.Count < 2) f2 = f1; + if(args.Length < 2) f2 = f1; this.i_down = (int)((f1<f2)?f1:f2); this.i_up = (int)((f1>f2)?f1:f2); this.i_count = this.i_down; - AddInlet(_list,new PureData.Symbol("bound")); + AddInlet(_list,new Symbol("bound")); AddInlet(ref step); AddOutlet(_float); @@ -33,14 +36,15 @@ public class Counter: // this function MUST exist private static void Setup(Counter obj) { - AddMethod(0,new Method(obj.Bang)); - AddMethod(0,"reset",new Method(obj.Reset)); - AddMethod(0,"set",new MethodFloat(obj.Set)); - AddMethod(0,"bound",new MethodList(obj.Bound)); + AddMethod(obj.Bang); + AddMethod(0,"reset",obj.Reset); + AddMethod(0,"set",obj.Set); + AddMethod(0,"bound",obj.Bound); } protected void Bang() { + float f = this.i_count; int step = (int)this.step; this.i_count += step; @@ -56,7 +60,7 @@ public class Counter: } } - Outlet(0,f); + Outlet(0,f); } protected void Reset() @@ -69,7 +73,7 @@ public class Counter: this.i_count = (int)f; } - protected void Bound(PureData.AtomList args) + protected void Bound(Atom[] args) { float f1 = (float)args[0]; float f2 = (float)args[1]; @@ -77,5 +81,4 @@ public class Counter: this.i_down = (int)((f1<f2)?f1:f2); this.i_up = (int)((f1>f2)?f1:f2); } - } diff --git a/Counter/Counter.csproj b/Counter/Counter.csproj index 4502d55..ab8a5eb 100644 --- a/Counter/Counter.csproj +++ b/Counter/Counter.csproj @@ -1,105 +1,107 @@ -<VisualStudioProject> - <CSHARP - ProjectType = "Local" - ProductVersion = "7.10.3077" - SchemaVersion = "2.0" - ProjectGuid = "{8CFEFB15-2A72-45B5-BC99-3BAFFB2B27C3}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "Counter" - AssemblyOriginatorKeyFile = "" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "Library" - PreBuildEvent = "" - PostBuildEvent = "" - RootNamespace = "Counter" - RunPostBuildEvent = "OnBuildSuccess" - StartupObject = "" - > - <Config - Name = "Debug" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "DEBUG;TRACE" - DocumentationFile = "" - DebugSymbols = "true" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "false" - OutputPath = "bin\Debug\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - <Config - Name = "Release" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "TRACE" - DocumentationFile = "" - DebugSymbols = "false" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "true" - OutputPath = "bin\Release\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.XML" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" - /> - <Reference - Name = "PureData" - Project = "{0015D5E7-B0FB-4F06-B334-225447D1F992}" - Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" - /> - </References> - </Build> - <Files> - <Include> - <File - RelPath = "AssemblyInfo.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File - RelPath = "Counter.cs" - SubType = "Code" - BuildAction = "Compile" - /> - </Include> - </Files> - </CSHARP> -</VisualStudioProject> - +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectType>Local</ProjectType> + <ProductVersion>8.0.50727</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{8CFEFB15-2A72-45B5-BC99-3BAFFB2B27C3}</ProjectGuid> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ApplicationIcon> + </ApplicationIcon> + <AssemblyKeyContainerName> + </AssemblyKeyContainerName> + <AssemblyName>Counter</AssemblyName> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + <DefaultClientScript>JScript</DefaultClientScript> + <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout> + <DefaultTargetSchema>IE50</DefaultTargetSchema> + <DelaySign>false</DelaySign> + <OutputType>Library</OutputType> + <RootNamespace>Counter</RootNamespace> + <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> + <StartupObject> + </StartupObject> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <OutputPath>bin\Debug\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>true</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>full</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <OutputPath>bin\Debug\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>false</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>true</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>none</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <ItemGroup> + <Reference Include="System"> + <Name>System</Name> + </Reference> + <Reference Include="System.Data"> + <Name>System.Data</Name> + </Reference> + <Reference Include="System.XML"> + <Name>System.XML</Name> + </Reference> + <ProjectReference Include="..\PureData\PureData.csproj"> + <Name>PureData</Name> + <Project>{0015D5E7-B0FB-4F06-B334-225447D1F992}</Project> + <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Compile Include="AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Counter.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent> + </PreBuildEvent> + <PostBuildEvent> + </PostBuildEvent> + </PropertyGroup> +</Project>
\ No newline at end of file diff --git a/PureData/Atom.cs b/PureData/Atom.cs index 6bad0b6..4e78eef 100755 --- a/PureData/Atom.cs +++ b/PureData/Atom.cs @@ -8,38 +8,57 @@ using System.Collections.Generic; namespace PureData { [StructLayout (LayoutKind.Sequential)] - public unsafe struct Symbol + public struct Symbol { // this should NOT be public (or at least read only) - private readonly void *sym; + private readonly IntPtr sym; public Symbol(string s) { - sym = Internal.SymGen(s); + this = Internal.SymGen(s); } public override string ToString() { - return Internal.SymEval(sym); + return Internal.SymEval(this); + } + + public static bool operator ==(Symbol s1,Symbol s2) + { + return s1.sym == s2.sym; + } + + public static bool operator !=(Symbol s1, Symbol s2) + { + return s1.sym != s2.sym; + } + + public override bool Equals(object o) + { + try { return this == (Symbol)o; } + catch {} + return false; + } + + public override int GetHashCode() + { + return (int)sym; } } [StructLayout (LayoutKind.Sequential)] - public unsafe struct Pointer + public struct Pointer { - private readonly void *ptr; + private readonly IntPtr ptr; public override string ToString() { - if(sizeof(void *) == 4) - return ((int)ptr).ToString(); - else - return ((long)ptr).ToString(); + return ptr.ToString(); } } [StructLayout (LayoutKind.Sequential)] - public unsafe struct Atom + public struct Atom { private enum AtomType {Null = 0, Float = 1, Symbol = 2, Pointer = 3}; @@ -146,7 +165,7 @@ namespace PureData } } - public class AtomListEnum + internal class AtomListEnum : IEnumerator { public AtomList list; @@ -192,8 +211,8 @@ namespace PureData // with l also being an AtomList... the two private members of the struct will get copied, although atoms is only a temporary reference [StructLayout (LayoutKind.Sequential)] - unsafe public struct AtomList -#if NET_2_0 + internal unsafe struct AtomList +#if xNET_2_0 : ICollection<Atom> #else : ICollection @@ -203,7 +222,7 @@ namespace PureData private readonly Atom *atoms; public int Count { get { return len; } } -#if NET_2_0 +#if xNET_2_0 public bool IsReadOnly { get { return false; } } // member of generic.ICollection<Atom> (C# 2.0) #endif public bool IsSynchronized { get { return false; } } @@ -212,7 +231,7 @@ namespace PureData // protect this from being used private AtomList(AtomList a) { len = 0; atoms = null; } -#if NET_2_0 +#if xNET_2_0 public void CopyTo(Atom[] array,int start) #else public void CopyTo(Array array,int start) @@ -246,7 +265,7 @@ namespace PureData } } -#if !NET_2_0 +//#if 1 // !NET_2_0 public static explicit operator Atom[](AtomList l) { Atom[] ret = new Atom[l.Count]; @@ -254,7 +273,7 @@ namespace PureData for(i = 0; i < l.Count; ++i) ret[i] = l.atoms[i]; return ret; } -#endif +//#endif override public string ToString() { diff --git a/PureData/DynamicMethod.cs b/PureData/DynamicMethod.cs new file mode 100644 index 0000000..749bb1a --- /dev/null +++ b/PureData/DynamicMethod.cs @@ -0,0 +1,101 @@ +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace PureData +{ + public delegate void DynamicMethodBang(External target); + public delegate void DynamicMethodFloat(External target,float f); + public delegate void DynamicMethodSymbol(External target,Symbol s); + public delegate void DynamicMethodPointer(External target,Pointer p); + public delegate void DynamicMethodList(External target,Atom[] l); + public delegate void DynamicMethodAnything(External target,int i,Symbol s,Atom[] l); + public delegate void DynamicMethodObject(External target,int i,object o); + + class DynamicMethods + { + private static Delegate CreateIntern(Delegate del, Type dyntype) + { + MethodInfo dynmethod = dyntype.GetMethod("Invoke"); + ParameterInfo[] dynparms = dynmethod.GetParameters(); + MethodInfo method = del.Method; + +#if DEBUG + if (dynmethod.ReturnType != typeof(void)) throw new ArgumentException("Return type must be void"); + + ParameterInfo[] parms = method.GetParameters(); + int numparms = parms.Length; + + if (dynparms.Length != numparms + 1) throw new ArgumentException("Number of parameters don't match"); + + for (int i = 0; i < numparms; ++i) + if (dynparms[i + 1].ParameterType != parms[i].ParameterType) throw new ArgumentException("Parameter types don't match"); +#endif + + Type[] argtypes = new Type[dynparms.Length]; + for (int i = 0; i < dynparms.Length; ++i) + argtypes[i] = dynparms[i].ParameterType; + + // Create dynamic method and obtain its IL generator to inject code. + DynamicMethod dynam = new DynamicMethod("dummy", typeof(void), argtypes, typeof(DynamicMethods)); + ILGenerator il = dynam.GetILGenerator(); + + #region IL Code generation + // If method isn't static push target instance on top of stack. + if (!method.IsStatic) + // Argument 0 of dynamic method is target instance. + il.Emit(OpCodes.Ldarg_0); + + // Push parameters onto the stack + for (int i = 0; i < dynparms.Length - 1; ++i) + il.Emit(OpCodes.Ldarg, i + 1); + + // Perform actual call. + // If method is not final a callvirt is required otherwise a normal call will be emitted. + il.Emit(method.IsFinal ? OpCodes.Call : OpCodes.Callvirt, method); + + // Emit return opcode. + il.Emit(OpCodes.Ret); + #endregion + + return dynam.CreateDelegate(dyntype); + } + + #region Specialized DynamicMethod makers + public static DynamicMethodBang Create(Public.MethodBang method) + { + return (DynamicMethodBang)CreateIntern(method, typeof(DynamicMethodBang)); + } + + public static DynamicMethodFloat Create(Public.MethodFloat method) + { + return (DynamicMethodFloat)CreateIntern(method,typeof(DynamicMethodFloat)); + } + + public static DynamicMethodSymbol Create(Public.MethodSymbol method) + { + return (DynamicMethodSymbol)CreateIntern(method,typeof(DynamicMethodSymbol)); + } + + public static DynamicMethodPointer Create(Public.MethodPointer method) + { + return (DynamicMethodPointer)CreateIntern(method,typeof(DynamicMethodPointer)); + } + + public static DynamicMethodList Create(Public.MethodList method) + { + return (DynamicMethodList)CreateIntern(method,typeof(DynamicMethodList)); + } + + public static DynamicMethodAnything Create(Public.MethodAnything method) + { + return (DynamicMethodAnything)CreateIntern(method,typeof(DynamicMethodAnything)); + } + + public static DynamicMethodObject Create(Public.MethodObject method) + { + return (DynamicMethodObject)CreateIntern(method, typeof(DynamicMethodObject)); + } + #endregion + } +} diff --git a/PureData/PureData.cs b/PureData/PureData.cs index 4df716e..0174317 100644 --- a/PureData/PureData.cs +++ b/PureData/PureData.cs @@ -1,203 +1,637 @@ using System; using System.Runtime.CompilerServices; // for extern import using System.Runtime.InteropServices; // for structures +using System.Reflection; +using System.Collections; namespace PureData { + [StructLayout(LayoutKind.Sequential)] + internal struct ClassPtr + { + private IntPtr ptr; + + public void Clear() { ptr = IntPtr.Zero; } + public bool Valid() { return ptr != IntPtr.Zero; } + + public override string ToString() { return ptr.ToString(); } + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ExternalPtr + { + private IntPtr ptr; + + public void Clear() { ptr = IntPtr.Zero; } + public bool Valid() { return ptr != IntPtr.Zero; } + + public override string ToString() { return ptr.ToString(); } + } + + // data passed from/to native side + [StructLayout(LayoutKind.Sequential)] + internal class PassedData + { + public Class klass; + public External ext; + public object obj; + } + // PD core functions - public unsafe class Internal + public class Internal { - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void *SymGen(string sym); + // the ExternalPtr when initializing an External instance + internal static ExternalPtr extptr; - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static string SymEval(void *sym); + internal static PassedData pass; // -------------------------------------------------------------------------- + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static Symbol SymGen(string sym); + [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj,Symbol sel,Symbol to_sel); + internal extern static string SymEval(Symbol sym); + + // -------------------------------------------------------------------------- + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj, Symbol sel, Symbol to_sel); // map to data member - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj,ref float f); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj, ref float f); // map to data member - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj,ref Symbol s); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj, ref Symbol s); // map to data member -// [MethodImplAttribute (MethodImplOptions.InternalCall)] -// internal extern static void AddInlet(void *obj,ref Pointer f); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj,ref Pointer f); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj,Symbol type); // create proxy inlet (typed) + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj, Symbol type); // create proxy inlet (typed) - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj); // create proxy inlet (anything) + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddInlet(ExternalPtr obj); // create proxy inlet (anything) // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddOutlet(void *obj,Symbol type); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void AddOutlet(ExternalPtr obj, Symbol type); // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,float f); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static void Outlet(ExternalPtr obj, int n); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,Symbol s); + internal extern static void Outlet(ExternalPtr obj, int n, float f); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,Pointer p); + internal extern static void Outlet(ExternalPtr obj, int n, Symbol s); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,Atom a); + internal extern static void Outlet(ExternalPtr obj, int n, Pointer p); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,Symbol s,AtomList l); + internal extern static void Outlet(ExternalPtr obj, int n, Atom a); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Outlet(void *obj,int n,Symbol s,Atom[] l); + internal extern static void Outlet(ExternalPtr obj, int n, Symbol s, Atom[] l); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void OutletEx(void *obj,int n,object o); + internal extern static void OutletEx(ExternalPtr obj, int n, object o); // -------------------------------------------------------------------------- [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Bind(void *obj,Symbol dst); + internal extern static void Bind(ExternalPtr obj, Symbol dst); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void Unbind(void *obj,Symbol dst); + internal extern static void Unbind(ExternalPtr obj, Symbol dst); } - - // This is the base class for a PD/CLR external - public unsafe abstract class External - { - // PD object pointer - private readonly void *ptr; + + public abstract class Public + : Internal + { // to be returned by Setup function - protected enum ClassType { Default = 0,PD = 1,GObj = 2,Patchable = 3,NoInlet = 8 } + protected enum ClassType { Default = 0, PD = 1, GObj = 2, Patchable = 3, NoInlet = 8 } // -------------------------------------------------------------------------- - protected readonly static Symbol _ = new Symbol(""); - protected readonly static Symbol _bang = new Symbol("bang"); - protected readonly static Symbol _float = new Symbol("float"); - protected readonly static Symbol _symbol = new Symbol("symbol"); - protected readonly static Symbol _pointer = new Symbol("pointer"); - protected readonly static Symbol _list = new Symbol("list"); - protected readonly static Symbol _anything = new Symbol("anything"); + public delegate void MethodBang(); + public delegate void MethodFloat(float f); + public delegate void MethodSymbol(Symbol s); + public delegate void MethodPointer(Pointer p); + public delegate void MethodList(Atom[] lst); + public delegate void MethodAnything(int inlet, Symbol tag, Atom[] lst); + public delegate void MethodObject(int inlet, object o); // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Post(string message); - - protected static void Post(string format,object arg0) { Post(String.Format(format,arg0)); } - protected static void Post(string format,object arg0,object arg1) { Post(String.Format(format,arg0,arg1)); } - protected static void Post(string format,object arg0,object arg1,object arg2) { Post(String.Format(format,arg0,arg1,arg2)); } - protected static void Post(string format,params object[] args) { Post(String.Format(format,args)); } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void PostError(string message); - - protected static void PostError(string format,object arg0) { PostError(String.Format(format,arg0)); } - protected static void PostError(string format,object arg0,object arg1) { PostError(String.Format(format,arg0,arg1)); } - protected static void PostError(string format,object arg0,object arg1,object arg2) { PostError(String.Format(format,arg0,arg1,arg2)); } - protected static void PostError(string format,params object[] args) { PostError(String.Format(format,args)); } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void PostVerbose(int lvl,string message); - - protected static void PostVerbose(int lvl,string format,object arg0) { PostVerbose(lvl,String.Format(format,arg0)); } - protected static void PostVerbose(int lvl,string format,object arg0,object arg1) { PostVerbose(lvl,String.Format(format,arg0,arg1)); } - protected static void PostVerbose(int lvl,string format,object arg0,object arg1,object arg2) { PostVerbose(lvl,String.Format(format,arg0,arg1,arg2)); } - protected static void PostVerbose(int lvl,string format,params object[] args) { PostVerbose(lvl,String.Format(format,args)); } + public readonly static Symbol _ = new Symbol(""); + public readonly static Symbol _bang = new Symbol("bang"); + public readonly static Symbol _float = new Symbol("float"); + public readonly static Symbol _symbol = new Symbol("symbol"); + public readonly static Symbol _pointer = new Symbol("pointer"); + public readonly static Symbol _list = new Symbol("list"); // -------------------------------------------------------------------------- - protected delegate void Method(); - protected delegate void MethodFloat(float f); - protected delegate void MethodSymbol(Symbol s); - protected delegate void MethodPointer(Pointer p); - protected delegate void MethodList(AtomList lst); - protected delegate void MethodAnything(int inlet,Symbol tag,AtomList lst); - protected delegate void MethodObject(int inlet,object o); + [MethodImplAttribute (MethodImplOptions.InternalCall)] + public extern static void Post(string message); - // -------------------------------------------------------------------------- + public static void Post(string format, object arg0) { Post(String.Format(format, arg0)); } + public static void Post(string format, object arg0, object arg1) { Post(String.Format(format, arg0, arg1)); } + public static void Post(string format, object arg0, object arg1, object arg2) { Post(String.Format(format, arg0, arg1, arg2)); } + public static void Post(string format, params object[] args) { Post(String.Format(format, args)); } [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Method m); + public extern static void PostError(string message); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodFloat m); + public static void PostError(string format, object arg0) { PostError(String.Format(format, arg0)); } + public static void PostError(string format, object arg0, object arg1) { PostError(String.Format(format, arg0, arg1)); } + public static void PostError(string format, object arg0, object arg1, object arg2) { PostError(String.Format(format, arg0, arg1, arg2)); } + public static void PostError(string format, params object[] args) { PostError(String.Format(format, args)); } [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodSymbol m); + public extern static void PostVerbose(int lvl, string message); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodPointer m); + public static void PostVerbose(int lvl, string format, object arg0) { PostVerbose(lvl, String.Format(format, arg0)); } + public static void PostVerbose(int lvl, string format, object arg0, object arg1) { PostVerbose(lvl, String.Format(format, arg0, arg1)); } + public static void PostVerbose(int lvl, string format, object arg0, object arg1, object arg2) { PostVerbose(lvl, String.Format(format, arg0, arg1, arg2)); } + public static void PostVerbose(int lvl, string format, params object[] args) { PostVerbose(lvl, String.Format(format, args)); } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodList m); + // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodAnything m); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static string SearchPath(string file); + } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,Method m); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,MethodFloat m); + public sealed class Class + : Public + { + // PD class pointer + private readonly ClassPtr ptr; + + // class type + private Type extclass; + + // -------------------------------------------------------------------------- + + // simple methods for inlet 0 + private DynamicMethodBang m_bang = null; + private DynamicMethodFloat m_float = null; + private DynamicMethodSymbol m_symbol = null; + private DynamicMethodPointer m_pointer = null; + private DynamicMethodList m_list = null; + private DynamicMethodAnything m_anything = null; + private DynamicMethodObject m_object = null; + + // -------------------------------------------------------------------------- + + private static void ResizeArray(ref Hashtable[] oldArray, int newSize) + { + int oldSize = oldArray.Length; + System.Type elementType = oldArray.GetType().GetElementType(); + Hashtable[] newArray = (Hashtable[])System.Array.CreateInstance(elementType, newSize); + int preserveLength = System.Math.Min(oldSize, newSize); + if (preserveLength > 0) + System.Array.Copy(oldArray, newArray, preserveLength); + oldArray = newArray; + } + + private struct MapValue + { + public MapValue(Kind k,Delegate d) { this.k = k; this.d = d; } + + public Kind k; + public Delegate d; + } + + private Hashtable[] m_map = new Hashtable[0]; + + // -------------------------------------------------------------------------- + + public override string ToString() + { + return extclass.Name; + } + + // -------------------------------------------------------------------------- + + private enum Kind { k_bang, k_float, k_symbol, k_pointer, k_list, k_anything, k_object } + + private enum MethodFlags { f_none = 0,f_bang = 0x01, f_float = 0x02, f_symbol = 0x04, f_pointer = 0x08, f_list = 0x10, f_anything = 0x20 } + + private static MethodFlags methodflags; + + + // -------------------------------------------------------------------------- + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static bool RegisterClass(ClassPtr ptr, Symbol sym, ClassType cflags, MethodFlags mflags); + + private void AddMethodIntern(int inlet, Symbol sel, Kind k, Delegate d) + { + // add to map + if (m_map.Length <= inlet) ResizeArray(ref m_map, inlet + 1); + Hashtable h = m_map[inlet]; + if(h == null) m_map[inlet] = h = new Hashtable(); + h[sel] = new MapValue(k, d); + + methodflags |= MethodFlags.f_anything; + } + + public void AddMethod(int inlet, Symbol sel, MethodBang d) + { + DynamicMethodBang dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _bang) + { + m_bang = dyn; + methodflags |= MethodFlags.f_bang; + } + else + AddMethodIntern(inlet, sel, Kind.k_bang, dyn); + } + + public void AddMethod(int inlet, Symbol sel, MethodFloat d) + { + DynamicMethodFloat dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _float) + { + m_float = dyn; + methodflags |= MethodFlags.f_float; + } + else + AddMethodIntern(inlet, sel, Kind.k_float, dyn); + } + + public void AddMethod(int inlet, Symbol sel, MethodSymbol d) + { + DynamicMethodSymbol dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _symbol) + { + m_symbol = dyn; + methodflags |= MethodFlags.f_symbol; + } + else + AddMethodIntern(inlet, sel, Kind.k_symbol, dyn); + } + + public void AddMethod(int inlet, Symbol sel, MethodPointer d) + { + DynamicMethodPointer dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _pointer) + { + m_pointer = dyn; + methodflags |= MethodFlags.f_pointer; + } + else + AddMethodIntern(inlet, sel, Kind.k_pointer, dyn); + } + + public void AddMethod(int inlet, Symbol sel, MethodList d) + { + DynamicMethodList dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _list) + { + m_list = dyn; + methodflags |= MethodFlags.f_list; + } + else + AddMethodIntern(inlet, sel, Kind.k_list, dyn); + } + + public void AddMethod(int inlet, Symbol sel, MethodAnything d) + { + DynamicMethodAnything dyn = DynamicMethods.Create(d); + if (inlet == 0 && sel == _) + { + m_anything = dyn; + methodflags |= MethodFlags.f_anything; + } + else + AddMethodIntern(inlet, sel, Kind.k_anything, dyn); + } + + public void AddMethod(int inlet, MethodObject d) + { + DynamicMethodObject dyn = DynamicMethods.Create(d); + m_object = dyn; + methodflags |= MethodFlags.f_anything; + } + + // -------------------------------------------------------------------------- + + private Class(ClassPtr p,Type c) + { + ptr = p; + extclass = c; + } + + private delegate void DelegateClass(ClassPtr ptr, Symbol sym); + private static void NewClass(ClassPtr ptr, Symbol sym) + { + Internal.pass.klass = null; + + try + { + string name = sym.ToString(); + + // load assembly according to name + string file = SearchPath(name + ".dll"); + if (file.Length == 0) return; // throw new ArgumentException("Assembly file " + name + " not found"); + Assembly assembly = Assembly.LoadFile(file); + if (assembly == null) return; // throw new ArgumentException("Assembly " + name + " could not be loaded"); + Type exttp = assembly.GetType(name); + if (exttp == null) throw new ArgumentException("Class " + name + " could not be found"); + + Class klass = new Class(ptr, exttp); + + // create dummy external + ConstructorInfo ctor = exttp.GetConstructor(System.Type.EmptyTypes); + if (ctor == null) throw new MissingMethodException("External class must have a default constructor"); + + Internal.pass.klass = klass; + Internal.extptr.Clear(); + + External dummy = (External)ctor.Invoke(null); + + // reset flags + methodflags = MethodFlags.f_none; + + // call Setup method + MethodInfo setup = exttp.GetMethod("Setup",BindingFlags.NonPublic|BindingFlags.Static,null, new Type[1] { exttp },null); + if (setup == null) throw new MissingMethodException("External class must have a Setup function"); + + object ret = setup.Invoke(exttp, new object[1] { dummy }); + ClassType classflags; + try { classflags = (ClassType)ret; } + catch { classflags = ClassType.Default; } + + // set callbacks + RegisterClass(ptr, sym, classflags, methodflags); + } + catch (Exception exc) + { + Internal.pass.klass = null; + PostError(exc.ToString()); + } + } + + private delegate void DelegateNew(ExternalPtr ptr,AtomList args); + private static void NewInstance(ExternalPtr ptr,AtomList args) + { + External instance; + + Class cl = Internal.pass.klass; // set by native side + Internal.extptr = ptr; + +// Post("CLASS-NEW {0}",cl); + try + { + // TODO: create dynamic delegate for that.... + System.Reflection.ConstructorInfo m = cl.extclass.GetConstructor(new Type[1] { typeof(Atom[]) }); + if (m != null) + instance = (External)m.Invoke(new object[1] { (Atom[])args }); + else + { + // search for the argument-less constructor... it must exist, we searched before + m = cl.extclass.GetConstructor(System.Type.EmptyTypes); + instance = (External)m.Invoke(null); + } + } + catch (Exception exc) + { + instance = null; + PostError(exc.ToString()); + } + +#if DEBUG + Internal.extptr.Clear(); +#endif + + Internal.pass.ext = instance; // back to native + } + + private delegate void DelegateBang(); + private static void CallBang() + { + External e = Internal.pass.ext; + try { e.klass.m_bang(e); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegateFloat(float f); + private static void CallFloat(float f) + { + External e = Internal.pass.ext; + try { e.klass.m_float(e, f); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegateSymbol(Symbol s); + private static void CallSymbol(Symbol s) + { + External e = Internal.pass.ext; + try { e.klass.m_symbol(e, s); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegatePointer(Pointer p); + private static void CallPointer(Pointer p) + { + External e = Internal.pass.ext; + try { e.klass.m_pointer(e, p); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegateList(AtomList l); + private static void CallList(AtomList l) + { + External e = Internal.pass.ext; + try { e.klass.m_list(e, (Atom[])l); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegateAnything(int inlet, Symbol s, AtomList l); + private static void CallAnything(int inlet, Symbol s, AtomList l) + { +// Post("CLASS-ANYTHING {0}->{1}:{2}", inlet,s,l); + + try { + External e = Internal.pass.ext; + Class c = e.klass; + + Hashtable h; + try { h = (Hashtable)c.m_map[inlet]; } + catch (IndexOutOfRangeException) { h = null; } + + if(h != null) + { + object fnd = h[s]; + if (fnd != null) + { + MapValue mv = (MapValue)fnd; + switch(mv.k) + { + case Kind.k_bang: + { + ((DynamicMethodBang)mv.d)(e); + return; + } + case Kind.k_float: + { + float f = l.Count > 0 ? (float)l[0] : 0; + ((DynamicMethodFloat)mv.d)(e, f); + return; + } + case Kind.k_symbol: + { + Symbol sym = l.Count > 0 ? (Symbol)l[0] : _; + ((DynamicMethodSymbol)mv.d)(e, sym); + return; + } + case Kind.k_pointer: + { + Pointer p = l.Count > 0 ? (Pointer)l[0] : new Pointer(); + ((DynamicMethodPointer)mv.d)(e, p); + return; + } + case Kind.k_list: + ((DynamicMethodList)mv.d)(e,(Atom[])l); + return; + case Kind.k_anything: + ((DynamicMethodAnything)mv.d)(e,inlet,s,(Atom[])l); + return; + default: + throw new NotImplementedException("Selector " + s.ToString() + " not handled"); + } + } + } + + // no explicit method found... + c.m_anything(e, inlet, s, (Atom[])l); + } + catch (Exception exc) { PostError(exc.ToString()); } + } + + private delegate void DelegateObject(int inlet); + private static void CallObject(int inlet) + { +// Post("CLASS-OBJECT {0}", inlet); + + External e = Internal.pass.ext; + try { e.klass.m_object(e, inlet, Internal.pass.obj); } + catch (Exception exc) { PostError(exc.ToString()); } + } + + // -------------------------------------------------------------------------- + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static void Register(DelegateClass d_class, DelegateNew d_new, DelegateBang d_bang, DelegateFloat d_float, DelegateSymbol d_symbol, DelegatePointer d_pointer, DelegateList d_list, DelegateAnything d_anything, DelegateObject d_object); + + private static void Setup() + { + try + { + Internal.pass = new PassedData(); + + Register( + new DelegateClass(NewClass), + new DelegateNew(NewInstance), + new DelegateBang(CallBang), + new DelegateFloat(CallFloat), + new DelegateSymbol(CallSymbol), + new DelegatePointer(CallPointer), + new DelegateList(CallList), + new DelegateAnything(CallAnything), + new DelegateObject(CallObject) + ); + } + catch (Exception exc) { PostError(exc.ToString()); } + } + } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,MethodSymbol m); + + // This is the base class for a PD/CLR external + public abstract class External + : Public + { + // PD object pointer + internal readonly ExternalPtr ptr; + // Class + internal readonly Class klass; - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,MethodPointer m); + // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,MethodList m); + protected External() + { + ptr = Internal.extptr; + klass = Internal.pass.klass; + } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,Symbol sel,MethodAnything m); + public override string ToString() + { + return ptr.Valid()?klass.ToString():"???"; + } - protected static void AddMethod(int inlet,string sel,Method m) { AddMethod(inlet,new Symbol(sel),m); } - protected static void AddMethod(int inlet,string sel,MethodFloat m) { AddMethod(inlet,new Symbol(sel),m); } - protected static void AddMethod(int inlet,string sel,MethodSymbol m) { AddMethod(inlet,new Symbol(sel),m); } - protected static void AddMethod(int inlet,string sel,MethodPointer m) { AddMethod(inlet,new Symbol(sel),m); } - protected static void AddMethod(int inlet,string sel,MethodList m) { AddMethod(inlet,new Symbol(sel),m); } - protected static void AddMethod(int inlet,string sel,MethodAnything m) { AddMethod(inlet,new Symbol(sel),m); } + // -------------------------------------------------------------------------- - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void AddMethod(int inlet,MethodObject m); + protected static void AddMethod(int inlet, Symbol sel, MethodBang m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, Symbol sel, MethodFloat m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, Symbol sel, MethodSymbol m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, Symbol sel, MethodPointer m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, Symbol sel, MethodList m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, Symbol sel, MethodAnything m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); } + protected static void AddMethod(int inlet, MethodObject m) { ((External)m.Target).klass.AddMethod(inlet, m); } + + protected static void AddMethod(int inlet, MethodBang m) { AddMethod(inlet, _bang, m); } + protected static void AddMethod(int inlet, MethodFloat m) { AddMethod(inlet, _float, m); } + protected static void AddMethod(int inlet, MethodSymbol m) { AddMethod(inlet, _symbol, m); } + protected static void AddMethod(int inlet, MethodPointer m) { AddMethod(inlet, _pointer, m); } + protected static void AddMethod(int inlet, MethodList m) { AddMethod(inlet, _list, m); } + protected static void AddMethod(int inlet, MethodAnything m) { AddMethod(inlet, _, m); } + + protected static void AddMethod(MethodBang m) { AddMethod(0, m); } + protected static void AddMethod(MethodFloat m) { AddMethod(0, m); } + protected static void AddMethod(MethodSymbol m) { AddMethod(0, m); } + protected static void AddMethod(MethodPointer m) { AddMethod(0, m); } + protected static void AddMethod(MethodList m) { AddMethod(0, m); } + protected static void AddMethod(MethodAnything m) { AddMethod(0, m); } + protected static void AddMethod(MethodObject m) { AddMethod(0, m); } + + protected static void AddMethod(int inlet, string sel, MethodBang m) { AddMethod(inlet, new Symbol(sel), m); } + protected static void AddMethod(int inlet, string sel, MethodFloat m) { AddMethod(inlet, new Symbol(sel), m); } + protected static void AddMethod(int inlet, string sel, MethodSymbol m) { AddMethod(inlet, new Symbol(sel), m); } + protected static void AddMethod(int inlet, string sel, MethodPointer m) { AddMethod(inlet, new Symbol(sel), m); } + protected static void AddMethod(int inlet, string sel, MethodList m) { AddMethod(inlet, new Symbol(sel), m); } + protected static void AddMethod(int inlet, string sel, MethodAnything m) { AddMethod(inlet, new Symbol(sel), m); } // -------------------------------------------------------------------------- - protected void AddInlet(ref float f) { Internal.AddInlet(ptr,ref f); } // map to data member - protected void AddInlet(ref Symbol s) { Internal.AddInlet(ptr,ref s); } // map to data member -// protected void AddInlet(ref Pointer p) { Internal.AddInlet(ptr,ref p); } // map to data member + protected void AddInlet(ref float f) { Internal.AddInlet(ptr, ref f); } // map to data member + protected void AddInlet(ref Symbol s) { Internal.AddInlet(ptr, ref s); } // map to data member + protected void AddInlet(ref Pointer p) { Internal.AddInlet(ptr,ref p); } // map to data member // protected void AddInlet(Symbol type) { Internal.AddInlet(ptr,type); } // create typed inlet protected void AddInlet() { Internal.AddInlet(ptr); } // create inlet responding to any message - protected void AddInlet(Symbol sel,Symbol to_sel) { Internal.AddInlet(ptr,sel,to_sel); } // redirect messages to defined selector + protected void AddInlet(Symbol sel, Symbol to_sel) { Internal.AddInlet(ptr, sel, to_sel); } // redirect messages to defined selector // -------------------------------------------------------------------------- - protected void AddOutlet(Symbol type) { Internal.AddOutlet(ptr,type); } + protected void AddOutlet(Symbol type) { Internal.AddOutlet(ptr, type); } protected void AddOutletBang() { AddOutlet(_bang); } protected void AddOutletFloat() { AddOutlet(_float); } protected void AddOutletSymbol() { AddOutlet(_symbol); } protected void AddOutletPointer() { AddOutlet(_pointer); } protected void AddOutletList() { AddOutlet(_list); } - protected void AddOutletAnything() { AddOutlet(_anything); } + protected void AddOutletAnything() { AddOutlet(_); } // -------------------------------------------------------------------------- @@ -206,9 +640,7 @@ namespace PureData protected void Outlet(int n,Symbol s) { Internal.Outlet(ptr,n,s); } protected void Outlet(int n,Pointer p) { Internal.Outlet(ptr,n,p); } protected void Outlet(int n,Atom a) { Internal.Outlet(ptr,n,a); } - protected void Outlet(int n,AtomList l) { Internal.Outlet(ptr,n,_list,l); } protected void Outlet(int n,Atom[] l) { Internal.Outlet(ptr,n,_list,l); } - protected void Outlet(int n,Symbol s,AtomList l) { Internal.Outlet(ptr,n,s,l); } protected void Outlet(int n,Symbol s,Atom[] l) { Internal.Outlet(ptr,n,s,l); } protected void OutletEx(int n,object o) { Internal.OutletEx(ptr,n,o); } @@ -223,17 +655,13 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Send(Symbol sym,Atom a); - protected static void Send(Symbol sym) { Send(sym,_bang,null); } + protected static void Send(Symbol sym) { Send(sym,_bang,new Atom[0]); } protected static void Send(Symbol sym,float f) { Send(sym,new Atom(f)); } protected static void Send(Symbol sym,Symbol s) { Send(sym,new Atom(s)); } protected static void Send(Symbol sym,Pointer p) { Send(sym,new Atom(p)); } - protected static void Send(Symbol sym,AtomList l) { Send(sym,_list,l); } protected static void Send(Symbol sym,Atom[] l) { Send(sym,_list,l); } [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Send(Symbol sym,Symbol s,AtomList l); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Send(Symbol sym,Symbol s,Atom[] l); [MethodImplAttribute (MethodImplOptions.InternalCall)] diff --git a/PureData/PureData.csproj b/PureData/PureData.csproj index f1b3d08..2d65f14 100644 --- a/PureData/PureData.csproj +++ b/PureData/PureData.csproj @@ -1,105 +1,108 @@ -<VisualStudioProject> - <CSHARP - ProjectType = "Local" - ProductVersion = "7.10.3077" - SchemaVersion = "2.0" - ProjectGuid = "{0015D5E7-B0FB-4F06-B334-225447D1F992}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "PureData" - AssemblyOriginatorKeyFile = "" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "Library" - PreBuildEvent = "" - PostBuildEvent = "" - RootNamespace = "PureData" - RunPostBuildEvent = "OnBuildSuccess" - StartupObject = "" - > - <Config - Name = "Debug" - AllowUnsafeBlocks = "true" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "DEBUG;TRACE" - DocumentationFile = "" - DebugSymbols = "true" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "false" - OutputPath = "bin\Debug\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - <Config - Name = "Release" - AllowUnsafeBlocks = "true" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "TRACE" - DocumentationFile = "" - DebugSymbols = "false" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "true" - OutputPath = "bin\Release\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.XML" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" - /> - </References> - </Build> - <Files> - <Include> - <File - RelPath = "AssemblyInfo.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File - RelPath = "Atom.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File - RelPath = "PureData.cs" - SubType = "Code" - BuildAction = "Compile" - /> - </Include> - </Files> - </CSHARP> -</VisualStudioProject> - +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectType>Local</ProjectType> + <ProductVersion>8.0.50727</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{0015D5E7-B0FB-4F06-B334-225447D1F992}</ProjectGuid> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ApplicationIcon> + </ApplicationIcon> + <AssemblyKeyContainerName> + </AssemblyKeyContainerName> + <AssemblyName>PureData</AssemblyName> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + <DefaultClientScript>JScript</DefaultClientScript> + <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout> + <DefaultTargetSchema>IE50</DefaultTargetSchema> + <DelaySign>false</DelaySign> + <OutputType>Library</OutputType> + <RootNamespace>PureData</RootNamespace> + <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> + <StartupObject> + </StartupObject> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <OutputPath>bin\Debug\</OutputPath> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>TRACE;DEBUG;NET_2_0</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>true</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>full</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <OutputPath>bin\Debug\</OutputPath> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>TRACE;DEBUG;NET_2_0</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>false</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>none</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <ItemGroup> + <Reference Include="System"> + <Name>System</Name> + </Reference> + <Reference Include="System.Data"> + <Name>System.Data</Name> + </Reference> + <Reference Include="System.Xml"> + <Name>System.XML</Name> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Atom.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="DynamicMethod.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="PureData.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent> + </PreBuildEvent> + <PostBuildEvent> + </PostBuildEvent> + </PropertyGroup> +</Project>
\ No newline at end of file @@ -7,6 +7,9 @@ extern "C" { #include <mono/metadata/debug-helpers.h> #include <mono/metadata/class.h> #include <mono/metadata/metadata.h> + +// we need this one - it's in mono-devel +gpointer mono_delegate_to_ftnptr (MonoDelegate *delegate); } #ifdef _MSC_VER @@ -30,6 +33,8 @@ extern "C" { #include <list> +#define CALL __stdcall + // main class library #define CORELIB "PureData" #define DLLEXT "dll" @@ -40,35 +45,42 @@ extern "C" { static t_symbol *sym_object; -// cached mono data -static MonoDomain *monodomain; -static MonoClass *clr_symbol,*clr_pointer,*clr_atom,*clr_atomlist,*clr_external; -static MonoMethodDesc *clr_desc_tostring,*clr_desc_ctor; -static MonoMethod *clr_meth_invoke; -static MonoProperty *clr_prop_method; +struct PassedData +{ + MonoObject object; + MonoObject *klass; + MonoObject *ext; + MonoObject *obj; +}; struct AtomList { - int argc; + AtomList(int c,t_atom *v): argc(c),argv(v) {} + + int argc; t_atom *argv; - - void Set(int c,t_atom *v) { argc = c,argv = v; } }; -// transforms a pointer (like MonoObject *) into a 3 element-list + +// cached mono data +static MonoDomain *monodomain; +static PassedData *clr_pass; + +// transforms a pointer (like MonoObject *) into a atom list +template <class T> struct ObjectAtom { // 64-bit safe... - enum { bitshift = 22,size = sizeof(void*)*8/bitshift+1 }; + enum { bitshift = 22,size = sizeof(T)*8/bitshift+1 }; t_atom msg[size]; ObjectAtom() {} - ObjectAtom(void *o) + ObjectAtom(T o) { - size_t ptr = (size_t)o; + long ptr = (long)o; for(int i = 0; i < size; ++i) { SETFLOAT(msg+i,(int)(ptr&((1<<bitshift)-1))); ptr >>= bitshift; @@ -83,139 +95,37 @@ struct ObjectAtom return true; } - static void *ptr(const t_atom *argv) + static T ptr(const t_atom *argv) { - size_t ret = 0; + long ret = 0; for(int i = size-1; i >= 0; --i) ret = (ret<<bitshift)+(int)argv[i].a_w.w_float; - return (void *)ret; + return (T)ret; } - template<class T> static T ptr(const t_atom *argv) { return (T)ptr(argv); } - operator t_atom *() { return msg; } }; -// temporary workspace items - -static MonoArray *clr_objarr_1,*clr_objarr_2,*clr_objarr_3; -static MonoObject *clr_obj_int,*clr_obj_single,*clr_obj_symbol,*clr_obj_pointer,*clr_obj_atomlist; -static int *clr_val_int; -static float *clr_val_single; -static t_symbol **clr_val_symbol; -static void **clr_val_pointer; -static AtomList *clr_val_atomlist; - - -struct t_clr; - -struct Delegate -{ - enum Kind { k_bang,k_float,k_symbol,k_pointer,k_list,k_anything,k_object }; - - inline operator bool() const { return methodinfo != NULL; } - - MonoObject *methodinfo; - MonoMethod *virtmethod; - Kind kind; - - inline void init(MonoObject *method,Kind k) - { - methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - assert(methodinfo); - virtmethod = mono_object_get_virtual_method(methodinfo,clr_meth_invoke); - assert(virtmethod); - kind = k; - } - - inline MonoObject *invoke(MonoObject *obj,void *arg) const - { - gpointer args[2] = {obj,arg}; - assert(methodinfo); - MonoObject *exc; - mono_runtime_invoke(virtmethod,methodinfo,args,&exc); - return exc; - } - - inline MonoObject *invokeatom(MonoObject *obj,MonoObject *atom) const - { - mono_array_set(clr_objarr_1,void*,0,atom); - return invoke(obj,clr_objarr_1); - } - - inline MonoObject *operator()(MonoObject *obj) const - { - return invoke(obj,NULL); - } - - inline MonoObject *operator()(MonoObject *obj,float f) const - { - *clr_val_single = f; - return invokeatom(obj,clr_obj_single); - } - - inline MonoObject *operator()(MonoObject *obj,t_symbol *s) const - { - *clr_val_symbol = s; - return invokeatom(obj,clr_obj_symbol); - } - - inline MonoObject *operator()(MonoObject *obj,t_gpointer *p) const - { - *clr_val_pointer = p; - return invokeatom(obj,clr_obj_pointer); - } - - inline MonoObject *operator()(MonoObject *obj,int argc,t_atom *argv) const - { - clr_val_atomlist->Set(argc,argv); - return invokeatom(obj,clr_obj_atomlist); - } - - inline MonoObject *operator()(MonoObject *obj,int inlet,t_symbol *s,int argc,t_atom *argv) const - { - *clr_val_int = inlet; - *clr_val_symbol = s; - clr_val_atomlist->Set(argc,argv); - mono_array_set(clr_objarr_3,void*,0,clr_obj_int); - mono_array_set(clr_objarr_3,void*,1,clr_obj_symbol); - mono_array_set(clr_objarr_3,void*,2,clr_obj_atomlist); - return invoke(obj,clr_objarr_3); - } - - inline MonoObject *operator()(MonoObject *obj,int inlet,MonoObject *clrobj) const - { - *clr_val_int = inlet; - mono_array_set(clr_objarr_2,void*,0,clr_obj_int); - mono_array_set(clr_objarr_2,void*,1,clrobj); - return invoke(obj,clr_objarr_2); - } -}; +enum Kind { k_bang, k_float, k_symbol, k_pointer, k_list, k_anything, k_object }; -typedef std::map<t_symbol *,Delegate> ClrMethodMap; -typedef std::vector<ClrMethodMap *> ClrMethods; // this is the class structure // holding the pd and mono class -// and our CLR method pointers struct t_clr_class { t_class *pd_class; - MonoClass *mono_class; - MonoMethod *mono_ctor; - MonoClassField *obj_field; // ptr field in PureData.External - t_symbol *name; - Delegate method_bang,method_float,method_symbol,method_pointer,method_list,method_anything,method_object; - ClrMethods *methods; // explicit method selectors + MonoObject *mono_class; }; static t_class *proxy_class; +struct t_instance; + struct t_proxy { t_object pd_obj; // myself - t_clr *parent; // parent object + t_instance *parent; // parent object int inlet; }; @@ -232,302 +142,144 @@ static t_clr_class *clr_setup_class = NULL; // inlet index... must start with 0 every time a new object is made static int clr_inlet; + // this is the class instance object structure -struct t_clr +struct t_instance { t_object pd_obj; // myself - t_clr_class *clr_clss; // pointer to our class structure + t_clr_class *pd_class; MonoObject *mono_obj; // the mono class instance - OutletArr *outlets; + guint32 mono_handle; // the mono class instance + + OutletArr *outlets; ProxyList *proxies; }; - +typedef void (__stdcall NewClass)(t_clr_class *c,const t_symbol *sym); +typedef void (__stdcall NewInstance)(t_instance *p,AtomList l); +typedef void (__stdcall CallBang)(); +typedef void (__stdcall CallFloat)(float f); +typedef void (__stdcall CallSymbol)(const t_symbol *sym); +typedef void (__stdcall CallPointer)(const t_gpointer *ptr); +typedef void (__stdcall CallList)(AtomList l); +typedef void (__stdcall CallAnything)(int inlet,const t_symbol *sym,AtomList l); +typedef void (__stdcall CallObject)(int inlet); + +static NewClass *newclass = NULL; +static NewInstance *newinstance = NULL; +static CallBang *callbang = NULL; +static CallFloat *callfloat = NULL; +static CallSymbol *callsymbol = NULL; +static CallPointer *callpointer = NULL; +static CallList *calllist = NULL; +static CallAnything *callanything = NULL; +static CallObject *callobject = NULL; + +#if 0 // Print error message given by exception -static void error_exc(char *txt,char *cname,MonoObject *exc) +static void error_exc(char* txt,char* cname,MonoObject* exc) { - MonoMethod *m = mono_method_desc_search_in_class(clr_desc_tostring,mono_get_exception_class()); + MonoMethod* m = mono_method_desc_search_in_class(clr_desc_tostring,mono_get_exception_class()); assert(m); m = mono_object_get_virtual_method(exc,m); assert(m); - MonoString *str = (MonoString *)mono_runtime_invoke(m,exc,NULL,NULL); + MonoString* str = (MonoString*)mono_runtime_invoke(m,exc,NULL,NULL); assert(str); error("CLR class %s: %s",txt,cname); error(mono_string_to_utf8(str)); } +#endif + -static void clr_method_bang(t_clr *x) +static void clr_method_bang(t_instance *x) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_bang(x->mono_obj); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callbang); + clr_pass->ext = x->mono_obj; + callbang(); } -static void clr_method_float(t_clr *x,t_float f) +static void clr_method_float(t_instance *x,t_float f) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_float(x->mono_obj,f); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callfloat); + clr_pass->ext = x->mono_obj; + callfloat(f); } -static void clr_method_symbol(t_clr *x,t_symbol *s) +static void clr_method_symbol(t_instance *x,t_symbol *s) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_symbol(x->mono_obj,s); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callsymbol); + clr_pass->ext = x->mono_obj; + callsymbol(s); } -static void clr_method_pointer(t_clr *x,t_gpointer *p) +static void clr_method_pointer(t_instance *x,t_gpointer *p) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_pointer(x->mono_obj,p); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callpointer); + clr_pass->ext = x->mono_obj; + callpointer(p); } -static void clr_method_list(t_clr *x,t_symbol *,int argc,t_atom *argv) +static void clr_method_list(t_instance *x,t_symbol *,int argc,t_atom *argv) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_list(x->mono_obj,argc,argv); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(calllist); + clr_pass->ext = x->mono_obj; + calllist(AtomList(argc,argv)); } -static void call_anything(t_clr *x,int inlet,t_symbol *s,int argc,t_atom *argv) +static void call_anything(t_instance *x,int inlet,t_symbol *s,int argc,t_atom *argv) { - assert(x && x->clr_clss); - - const Delegate *d; - - ClrMethods *methods = x->clr_clss->methods; - if(methods && inlet < (int)methods->size()) { - ClrMethodMap *methmap = (*methods)[inlet]; - if(methmap) { - ClrMethodMap::iterator it = methmap->find(s); - if(it != methmap->end()) { - d = &it->second; - goto found; - } - - if(inlet) { - // search for NULL symbol pointer - it = methmap->find(NULL); - if(it != methmap->end()) { - d = &it->second; - goto found; - } - } - } - } - - // no selectors: general method - d = &x->clr_clss->method_anything; - - found: - - // we must have found something.... - assert(d); - - MonoObject *exc; - switch(d->kind) { - case Delegate::k_bang: - exc = (*d)(x->mono_obj); - break; - case Delegate::k_float: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_FLOAT) - exc = (*d)(x->mono_obj,argv[0].a_w.w_float); - else { - error("%s - %s handler: float argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - break; - case Delegate::k_symbol: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_SYMBOL) - exc = (*d)(x->mono_obj,argv[0].a_w.w_symbol); - else { - error("%s - %s handler: symbol argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - break; - case Delegate::k_pointer: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_POINTER) - exc = (*d)(x->mono_obj,argv[0].a_w.w_gpointer); - else { - error("%s - %s handler: pointer argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - break; - case Delegate::k_list: - exc = (*d)(x->mono_obj,argc,argv); - break; - case Delegate::k_anything: - exc = (*d)(x->mono_obj,inlet,s,argc,argv); - break; - case Delegate::k_object: - if(s != sym_object || !ObjectAtom::check(argc,argv)) { - error("CLR - object handler: invalid arguments"); - return; - } - exc = (*d)(x->mono_obj,inlet,ObjectAtom::ptr<MonoObject *>(argv)); - break; - default: - assert(false); - } - - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + clr_pass->ext = x->mono_obj; + if(s == sym_object && ObjectAtom<guint32>::check(argc,argv)) { + assert(callobject); + guint32 hnd = ObjectAtom<guint32>::ptr(argv); + clr_pass->obj = mono_gchandle_get_target(hnd); + callobject(inlet); + } + else { + assert(callanything); + callanything(inlet,s,AtomList(argc,argv)); + } } -static void clr_method_anything(t_clr *x,t_symbol *s,int argc,t_atom *argv) { call_anything(x,0,s,argc,argv); } +static void clr_method_anything(t_instance *x,t_symbol *s,int argc,t_atom *argv) { call_anything(x,0,s,argc,argv); } static void clr_method_proxy(t_proxy *x,t_symbol *s,int argc,t_atom *argv) { call_anything(x->parent,x->inlet,s,argc,argv); } -static void PD_Post(MonoString *str) +static void CALL PD_Post(MonoString *str) { post("%s",mono_string_to_utf8(str)); } -static void PD_PostError(MonoString *str) +static void CALL PD_PostError(MonoString *str) { error("%s",mono_string_to_utf8(str)); } -static void PD_PostVerbose(int lvl,MonoString *str) +static void CALL PD_PostVerbose(int lvl,MonoString *str) { verbose(lvl,"%s",mono_string_to_utf8(str)); } -static void *PD_SymGen(MonoString *str) +static void *CALL PD_SymGen(MonoString *str) { assert(str); return gensym(mono_string_to_utf8(str)); } -static MonoString *PD_SymEval(t_symbol *sym) +static MonoString *CALL PD_SymEval(t_symbol *sym) { assert(sym); return mono_string_new(monodomain,sym->s_name); } -static void PD_AddMethodHandler(int inlet,t_symbol *sym,MonoObject *method,Delegate::Kind kind) -{ - assert(clr_setup_class); - Delegate d; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); - d.kind = kind; - - ClrMethods *ms = clr_setup_class->methods; - if(!ms) - clr_setup_class->methods = ms = new ClrMethods; - - ClrMethodMap *m; - if(inlet >= (int)ms->size()) { - ms->resize(inlet+1,NULL); - (*ms)[inlet] = m = new ClrMethodMap; - } - else - m = (*ms)[inlet]; - assert(m); - - // add tag to map - (*m)[sym] = d; -} - -static void PD_AddMethodBang(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,&s_bang,method,Delegate::k_bang); - else { - assert(clr_setup_class); - clr_setup_class->method_bang.init(method,Delegate::k_bang); - } -} - -static void PD_AddMethodFloat(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,&s_float,method,Delegate::k_float); - else { - assert(clr_setup_class); - clr_setup_class->method_float.init(method,Delegate::k_float); - } -} - -static void PD_AddMethodSymbol(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,&s_symbol,method,Delegate::k_symbol); - else { - assert(clr_setup_class); - clr_setup_class->method_symbol.init(method,Delegate::k_symbol); - } -} - -static void PD_AddMethodPointer(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,&s_pointer,method,Delegate::k_pointer); - else { - assert(clr_setup_class); - clr_setup_class->method_pointer.init(method,Delegate::k_pointer); - } -} - -static void PD_AddMethodList(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,&s_list,method,Delegate::k_list); - else { - assert(clr_setup_class); - clr_setup_class->method_list.init(method,Delegate::k_list); - } -} - -static void PD_AddMethodAnything(int inlet,MonoObject *method) -{ - if(inlet) - PD_AddMethodHandler(inlet,NULL,method,Delegate::k_anything); - else { - assert(clr_setup_class); - clr_setup_class->method_anything.init(method,Delegate::k_anything); - } -} - -static void PD_AddMethodSelBang(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_bang); -} - -static void PD_AddMethodSelFloat(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_float); -} - -static void PD_AddMethodSelSymbol(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_symbol); -} -static void PD_AddMethodSelPointer(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_pointer); -} - -static void PD_AddMethodSelList(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_list); -} - -static void PD_AddMethodSelAnything(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_anything); -} - -static void PD_AddMethodObject(int inlet,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym_object,method,Delegate::k_object); -} - - -static void PD_AddInletAlias(t_clr *obj,t_symbol *sel,t_symbol *to_sel) +static void CALL PD_AddInletAlias(t_instance *obj,t_symbol *sel,t_symbol *to_sel) { ++clr_inlet; assert(obj); @@ -535,7 +287,7 @@ static void PD_AddInletAlias(t_clr *obj,t_symbol *sel,t_symbol *to_sel) assert(in); } -static void PD_AddInletFloat(t_clr *obj,float *f) +static void CALL PD_AddInletFloat(t_instance *obj,float *f) { ++clr_inlet; assert(obj); @@ -543,7 +295,7 @@ static void PD_AddInletFloat(t_clr *obj,float *f) assert(in); } -static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) +static void CALL PD_AddInletSymbol(t_instance *obj,t_symbol **s) { ++clr_inlet; assert(obj); @@ -552,7 +304,7 @@ static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) } /* -static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) +static void CALL PD_AddInletPointer(t_clr *obj,t_gpointer *p) { ++clr_inlet; assert(obj); @@ -561,7 +313,7 @@ static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) } */ -static void PD_AddInletProxyTyped(t_clr *obj,t_symbol *type) +static void CALL PD_AddInletProxyTyped(t_instance *obj,t_symbol *type) { assert(obj); t_proxy *p = (t_proxy *)pd_new(proxy_class); @@ -573,10 +325,10 @@ static void PD_AddInletProxyTyped(t_clr *obj,t_symbol *type) assert(in); } -static void PD_AddInletProxy(t_clr *obj) { PD_AddInletProxyTyped(obj,NULL); } +static void CALL PD_AddInletProxy(t_instance *obj) { PD_AddInletProxyTyped(obj,NULL); } -static void PD_AddOutlet(t_clr *obj,t_symbol *type) +static void CALL PD_AddOutlet(t_instance *obj,t_symbol *type) { assert(obj); t_outlet *out = outlet_new(&obj->pd_obj,type); @@ -585,7 +337,7 @@ static void PD_AddOutlet(t_clr *obj,t_symbol *type) obj->outlets->push_back(out); } -static void PD_OutletBang(t_clr *obj,int n) +static void CALL PD_OutletBang(t_instance *obj,int n) { assert(obj); assert(obj->outlets); @@ -593,7 +345,7 @@ static void PD_OutletBang(t_clr *obj,int n) outlet_bang((*obj->outlets)[n]); } -static void PD_OutletFloat(t_clr *obj,int n,float f) +static void CALL PD_OutletFloat(t_instance *obj,int n,float f) { assert(obj); assert(obj->outlets); @@ -601,7 +353,7 @@ static void PD_OutletFloat(t_clr *obj,int n,float f) outlet_float((*obj->outlets)[n],f); } -static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) +static void CALL PD_OutletSymbol(t_instance *obj,int n,t_symbol *s) { assert(obj); assert(obj->outlets); @@ -609,7 +361,7 @@ static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) outlet_symbol((*obj->outlets)[n],s); } -static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) +static void CALL PD_OutletPointer(t_instance *obj,int n,t_gpointer *p) { assert(obj); assert(obj->outlets); @@ -617,12 +369,12 @@ static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) outlet_pointer((*obj->outlets)[n],p); } -static void PD_OutletAtom(t_clr *obj,int n,t_atom l) +static void CALL PD_OutletAtom(t_instance *obj,int n,t_atom l) { assert(obj); assert(obj->outlets); assert(n >= 0 && n < (int)obj->outlets->size()); - t_outlet *out = (*obj->outlets)[n]; + t_outlet* out = (*obj->outlets)[n]; switch(l.a_type) { case A_FLOAT: outlet_float(out,l.a_w.w_float); break; case A_SYMBOL: outlet_symbol(out,l.a_w.w_symbol); break; @@ -631,15 +383,7 @@ static void PD_OutletAtom(t_clr *obj,int n,t_atom l) } } -static void PD_OutletAnything(t_clr *obj,int n,t_symbol *s,AtomList l) -{ - assert(obj); - assert(obj->outlets); - assert(n >= 0 && n < (int)obj->outlets->size()); - outlet_anything((*obj->outlets)[n],s,l.argc,l.argv); -} - -static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) +static void CALL PD_OutletAnything(t_instance *obj,int n,t_symbol *s,MonoArray *l) { assert(obj); assert(obj->outlets); @@ -649,50 +393,68 @@ static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) } -static void PD_OutletObject(t_clr *obj,int n,MonoObject *o) +static void CALL PD_OutletObject(t_instance *obj,int n,MonoObject *o) { assert(obj); assert(obj->outlets); assert(n >= 0 && n < (int)obj->outlets->size()); - ObjectAtom oa(o); + guint32 hnd = mono_gchandle_new(o,TRUE); + ObjectAtom<guint32> oa(hnd); outlet_anything((*obj->outlets)[n],sym_object,oa.size,oa); + mono_gchandle_free(hnd); } -static void PD_SendAtom(t_symbol *dst,t_atom a) +static void CALL PD_SendAtom(t_symbol *dst,t_atom a) { void *cl = dst->s_thing; if(cl) pd_forwardmess((t_class **)cl,1,&a); } -static void PD_SendAnything(t_symbol *dst,t_symbol *s,AtomList l) -{ - void *cl = dst->s_thing; - if(cl) pd_typedmess((t_class **)cl,s,l.argc,l.argv); -} - -static void PD_SendAnything2(t_symbol *dst,t_symbol *s,MonoArray *l) +static void CALL PD_SendAnything(t_symbol *dst,t_symbol *s,MonoArray *l) { void *cl = dst->s_thing; // assert(mono_object_get_class(&l->obj) == clr_atom); if(cl) pd_typedmess((t_class **)cl,s,mono_array_length(l),mono_array_addr(l,t_atom,0)); } -static void PD_SendObject(t_symbol *dst,MonoObject *o) +static void CALL PD_SendObject(t_symbol *dst,MonoObject *o) { void *cl = dst->s_thing; // assert(mono_object_get_class(&l->obj) == clr_atom); if(cl) { - ObjectAtom oa(o); + guint32 hnd = mono_gchandle_new(o,TRUE); + ObjectAtom<guint32> oa(hnd); pd_typedmess((t_class **)cl,sym_object,oa.size,oa); + mono_gchandle_free(hnd); } } +static MonoString *CALL PD_SearchPath(MonoString *file) +{ + char *filestr = mono_string_to_utf8(file); + char dirbuf[MAXPDSTRING],*nameptr; + // search for classname.dll in the PD path + int fd; + if ((fd = open_via_path("",filestr,"",dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) { + // found + if(dirbuf != nameptr) { + // fix for the fact that open_via_path doesn't return a path, when it's found in . + strcat(dirbuf,"/"); + strcat(dirbuf,filestr); + +// close(fd); // strange - we get an assertion failure here... + } + return mono_string_new(monodomain,dirbuf); + } + else + return mono_string_new(monodomain,""); +} + void *clr_new(t_symbol *classname, int argc, t_atom *argv) { - // find class name in map - + // find class name in map ClrMap::iterator it = clr_map.find(classname); if(it == clr_map.end()) { error("CLR - class %s not found",classname->s_name); @@ -702,51 +464,37 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) t_clr_class *clss = it->second; // make instance - t_clr *x = (t_clr *)pd_new(clss->pd_class); - x->mono_obj = mono_object_new (monodomain,clss->mono_class); - if(!x->mono_obj) { - pd_free((t_pd *)x); - error("CLR - class %s could not be instantiated",classname->s_name); - return NULL; - } - - // store class pointer - x->clr_clss = clss; - x->clr_clss->name = classname; - - // store our object pointer in External::ptr member - mono_field_set_value(x->mono_obj,clss->obj_field,x); - + t_instance *x = (t_instance *)pd_new(clss->pd_class); + x->pd_class = clss; x->outlets = NULL; x->proxies = NULL; - // ok, we have an object - look for constructor - if(clss->mono_ctor) { - // reset inlet index - clr_inlet = 0; + clr_inlet = 0; - AtomList al; - al.Set(argc,argv); - gpointer args = &al; + assert(newinstance); - // call constructor - MonoObject *exc; - mono_runtime_invoke(clss->mono_ctor,x->mono_obj,&args,&exc); - - if(exc) { - pd_free((t_pd *)x); - error_exc("exception raised in constructor",classname->s_name,exc); - return NULL; - } - } - else - verbose(1,"CLR - Warning: no constructor for class %s found",classname->s_name); + clr_pass->klass = clss->mono_class; + newinstance(x,AtomList(argc,argv)); + x->mono_obj = clr_pass->ext; +#ifdef _DEBUG + clr_pass->klass = NULL; +#endif - return x; + if(x->mono_obj) { + x->mono_handle = mono_gchandle_new(x->mono_obj,TRUE); + return x; + } + else { + pd_free((t_pd *)x); + error("CLR - class %s could not be instantiated",classname->s_name); + return NULL; + } } -void clr_free(t_clr *obj) +void clr_free(t_instance *obj) { + mono_gchandle_free(obj->mono_handle); + if(obj->outlets) delete obj->outlets; if(obj->proxies) { @@ -755,129 +503,67 @@ void clr_free(t_clr *obj) } } -static int classloader(char *dirname, char *classname, char *altname) +static void CALL PD_Register(MonoDelegate *d_class,MonoDelegate *d_new,MonoDelegate *d_bang,MonoDelegate *d_float,MonoDelegate *d_symbol,MonoDelegate *d_pointer,MonoDelegate *d_list,MonoDelegate *d_anything,MonoDelegate *d_object) { - t_clr_class *clr_class = NULL; - t_symbol *classsym; - MonoAssembly *assembly; - MonoImage *image; - MonoMethod *method; - int flags = CLASS_DEFAULT; - - char *realname; - char dirbuf[MAXPDSTRING],*nameptr; - // search for classname.dll in the PD path - int fd; - if ((fd = open_via_path(dirname, realname = classname, "." DLLEXT, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) - if (!altname || (fd = open_via_path(dirname, realname = altname, "." DLLEXT, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) - // not found - goto bailout; - - // found - close(fd); - - clr_class = (t_clr_class *)getbytes(sizeof(t_clr_class)); - // set all struct members to 0 - memset(clr_class,0,sizeof(*clr_class)); - - // try to load assembly - strcat(dirbuf,"/"); - strcat(dirbuf,realname); - strcat(dirbuf,"." DLLEXT); + newclass = (NewClass *)mono_delegate_to_ftnptr(d_class); + newinstance = (NewInstance *)mono_delegate_to_ftnptr(d_new); + callbang = (CallBang *)mono_delegate_to_ftnptr(d_bang); + callfloat = (CallFloat *)mono_delegate_to_ftnptr(d_float); + callsymbol = (CallSymbol *)mono_delegate_to_ftnptr(d_symbol); + callpointer = (CallPointer *)mono_delegate_to_ftnptr(d_pointer); + calllist = (CallList *)mono_delegate_to_ftnptr(d_list); + callanything = (CallAnything *)mono_delegate_to_ftnptr(d_anything); + callobject = (CallObject *)mono_delegate_to_ftnptr(d_object); +} - assembly = mono_domain_assembly_open(monodomain,dirbuf); - if(!assembly) { - error("clr: file %s couldn't be loaded!",dirbuf); - goto bailout; +static bool CALL PD_RegisterClass(t_clr_class *c,t_symbol *classsym,int classflags,int methodflags) +{ + assert(c && !c->pd_class); + c->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_instance), classflags, A_GIMME, A_NULL); + if(c->pd_class) { + if(methodflags&0x01) class_addbang(c->pd_class,clr_method_bang); + if(methodflags&0x02) class_addfloat(c->pd_class,clr_method_float); + if(methodflags&0x04) class_addsymbol(c->pd_class,clr_method_symbol); + if(methodflags&0x08) class_addpointer(c->pd_class,clr_method_pointer); + if(methodflags&0x10) class_addlist(c->pd_class,clr_method_list); + if(methodflags&0x20) class_addanything(c->pd_class,clr_method_anything); + return true; } + else + return false; +} - image = mono_assembly_get_image(assembly); - assert(image); - // try to find class - // "" means no namespace - clr_class->mono_class = mono_class_from_name(image,"",realname); - if(!clr_class->mono_class) { - error("Can't find %s class in %s\n",classname,mono_image_get_filename(image)); - goto bailout; +static int classloader(char *dirname, char *classname, char *altname) +{ + if(!newclass) { + post("CLR - Entry point not set"); + return 0; } - // make new class (with classname) - classsym = gensym(classname); - clr_class->pd_class = NULL; - - clr_class->obj_field = mono_class_get_field_from_name(clr_class->mono_class,"ptr"); - assert(clr_class->obj_field); - - // find static Setup method - MonoMethodDesc *clr_desc_main = mono_method_desc_new("::Setup",FALSE); - assert(clr_desc_main); + t_symbol *classsym = gensym(classname); - method = mono_method_desc_search_in_class(clr_desc_main,clr_class->mono_class); - if(method) { - MonoObject *obj = mono_object_new(monodomain,clr_class->mono_class); - if(!obj) { - error("CLR class %s could not be instantiated",classname); - goto bailout; - } - - // store NULL in External::ptr member - mono_field_set_value(obj,clr_class->obj_field,NULL); - - // set current class - clr_setup_class = clr_class; + t_clr_class *classdef = (t_clr_class *)getbytes(sizeof(t_clr_class)); + // set all struct members to 0 + memset(classdef,0,sizeof(t_clr_class)); - // call static Setup method - gpointer args = obj; - MonoObject *exc; - MonoObject *ret = mono_runtime_invoke(method,NULL,&args,&exc); - if(ret) { - // \TODO check return type - flags = *(int *)mono_object_unbox(ret); - } + newclass(classdef,classsym); + classdef->mono_class = clr_pass->klass; - // unset current class - clr_setup_class = NULL; + if(!classdef->mono_class) + { + freebytes(classdef,sizeof(t_clr_class)); + return 0; + } - if(exc) { - error_exc("CLR - Exception raised by Setup",classname,exc); - goto bailout; - } - } - else - post("CLR - Warning: no %s.Setup method found",classname); - - // find and save constructor - clr_class->mono_ctor = mono_method_desc_search_in_class(clr_desc_ctor,clr_class->mono_class); - - // make pd class - clr_class->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_clr), flags, A_GIMME, A_NULL); - - // register methods - if(clr_class->method_bang) - class_addbang(clr_class->pd_class,clr_method_bang); - if(clr_class->method_float) - class_addfloat(clr_class->pd_class,clr_method_float); - if(clr_class->method_symbol) - class_addsymbol(clr_class->pd_class,clr_method_symbol); - if(clr_class->method_pointer) - class_addpointer(clr_class->pd_class,clr_method_pointer); - if(clr_class->method_list) - class_addlist(clr_class->pd_class,clr_method_list); - if(clr_class->method_anything || clr_class->methods) - class_addanything(clr_class->pd_class,clr_method_anything); + mono_gchandle_new(classdef->mono_class,TRUE); // we don't remember the handle... won't be freed later // put into map - clr_map[classsym] = clr_class; + clr_map[classsym] = classdef; verbose(1,"CLR - Loaded class %s OK",classname); return 1; - -bailout: - if(clr_class) freebytes(clr_class,sizeof(t_clr_class)); - - return 0; } extern "C" @@ -902,26 +588,29 @@ void clr_setup(void) mono_set_dirs(tlib,tconf); #endif + // try to find PureData.dll in the PD path + char dirbuf[MAXPDSTRING],*nameptr; + // search in the PD path + int fd; + if ((fd = open_via_path("",CORELIB,"." DLLEXT,dirbuf,&nameptr,MAXPDSTRING,1)) >= 0) { + if(dirbuf != nameptr) // fix for the fact that open_via_path doesn't return a path, when it's found in . + strcat(dirbuf,"/" CORELIB "." DLLEXT); +// close(fd); // strange - we get an assertion failure here... + } + else { + error("CLR - " CORELIB "." DLLEXT " not found in path"); + return; + } + try { - monodomain = mono_jit_init(CORELIB); + monodomain = mono_jit_init(dirbuf); } catch(...) { monodomain = NULL; } - if(monodomain) { - // try to find PureData.dll in the PD path - char dirbuf[MAXPDSTRING],*nameptr; - // search in the PD path - int fd; - if ((fd = open_via_path("",CORELIB,"." DLLEXT,dirbuf,&nameptr,MAXPDSTRING,1)) >= 0) { - if(dirbuf != nameptr) // fix for the fact that open_via_path doesn't return a path, when it's found in . - strcat(dirbuf,"/" CORELIB "." DLLEXT); - close(fd); - } - else - strcpy(dirbuf,CORELIB "." DLLEXT); + if(monodomain) { // look for PureData.dll MonoAssembly *assembly = mono_domain_assembly_open (monodomain,dirbuf); if(!assembly) { @@ -935,92 +624,43 @@ void clr_setup(void) // add mono to C hooks mono_add_internal_call("PureData.Internal::SymGen(string)", (const void *)PD_SymGen); - mono_add_internal_call("PureData.Internal::SymEval(void*)", (const void *)PD_SymEval); - - mono_add_internal_call("PureData.External::Post(string)",(const void *)PD_Post); - mono_add_internal_call("PureData.External::PostError(string)",(const void *)PD_PostError); - mono_add_internal_call("PureData.External::PostVerbose(int,string)",(const void *)PD_PostVerbose); - - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/Method)", (const void *)PD_AddMethodBang); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodFloat)", (const void *)PD_AddMethodFloat); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodSymbol)", (const void *)PD_AddMethodSymbol); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodPointer)", (const void *)PD_AddMethodPointer); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodList)", (const void *)PD_AddMethodList); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodAnything)", (const void *)PD_AddMethodAnything); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/Method)", (const void *)PD_AddMethodSelBang); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodFloat)", (const void *)PD_AddMethodSelFloat); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodSymbol)", (const void *)PD_AddMethodSelSymbol); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodPointer)", (const void *)PD_AddMethodSelPointer); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodList)", (const void *)PD_AddMethodSelList); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodAnything)", (const void *)PD_AddMethodSelAnything); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodObject)", (const void *)PD_AddMethodObject); - - mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInletAlias); - mono_add_internal_call("PureData.Internal::AddInlet(void*,single&)", (const void *)PD_AddInletFloat); - mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol&)", (const void *)PD_AddInletSymbol); -// mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Pointer&)", (const void *)PD_AddInletPointer); -// mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol)", (const void *)PD_AddInletTyped); - mono_add_internal_call("PureData.Internal::AddInlet(void*)", (const void *)PD_AddInletProxy); - - mono_add_internal_call("PureData.Internal::AddOutlet(void*,PureData.Symbol)", (const void *)PD_AddOutlet); - - mono_add_internal_call("PureData.Internal::Outlet(void*,int)", (const void *)PD_OutletBang); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,single)", (const void *)PD_OutletFloat); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol)", (const void *)PD_OutletSymbol); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Pointer)", (const void *)PD_OutletPointer); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Atom)", (const void *)PD_OutletAtom); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.AtomList)", (const void *)PD_OutletAnything); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.Atom[])", (const void *)PD_OutletAnything2); - mono_add_internal_call("PureData.Internal::OutletEx(void*,int,object)", (const void *)PD_OutletObject); - -// mono_add_internal_call("PureData.Internal::Bind(void*,PureData.Symbol)", (const void *)PD_Bind); -// mono_add_internal_call("PureData.Internal::Unbind(void*,PureData.Symbol)", (const void *)PD_Unbind); + mono_add_internal_call("PureData.Internal::SymEval(PureData.Symbol)", (const void *)PD_SymEval); + + mono_add_internal_call("PureData.Public::Post(string)",(const void *)PD_Post); + mono_add_internal_call("PureData.Public::PostError(string)",(const void *)PD_PostError); + mono_add_internal_call("PureData.Public::PostVerbose(int,string)",(const void *)PD_PostVerbose); + mono_add_internal_call("PureData.Public::SearchPath(string)",(const void *)PD_SearchPath); + + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInletAlias); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,single&)", (const void *)PD_AddInletFloat); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol&)", (const void *)PD_AddInletSymbol); +// mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Pointer&)", (const void *)PD_AddInletPointer); +// mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_AddInletTyped); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr)", (const void *)PD_AddInletProxy); + + mono_add_internal_call("PureData.Internal::AddOutlet(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_AddOutlet); + + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int)", (const void *)PD_OutletBang); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,single)", (const void *)PD_OutletFloat); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Symbol)", (const void *)PD_OutletSymbol); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Pointer)", (const void *)PD_OutletPointer); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Atom)", (const void *)PD_OutletAtom); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Symbol,PureData.Atom[])", (const void *)PD_OutletAnything); + mono_add_internal_call("PureData.Internal::OutletEx(PureData.ExternalPtr,int,object)", (const void *)PD_OutletObject); + +// mono_add_internal_call("PureData.Internal::Bind(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_Bind); +// mono_add_internal_call("PureData.Internal::Unbind(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_Unbind); + + mono_add_internal_call("PureData.Class::Register(PureData.Class/DelegateClass,PureData.Class/DelegateNew,PureData.Class/DelegateBang,PureData.Class/DelegateFloat,PureData.Class/DelegateSymbol,PureData.Class/DelegatePointer,PureData.Class/DelegateList,PureData.Class/DelegateAnything,PureData.Class/DelegateObject)", (const void *)PD_Register); + mono_add_internal_call("PureData.Class::RegisterClass(PureData.ClassPtr,PureData.Symbol,PureData.Public/ClassType,PureData.Class/MethodFlags)", (const void *)PD_RegisterClass); +// mono_add_internal_call("PureData.Class::AddMethodIntern(PureData.ClassPtr,int,PureData.Symbol,PureData.Class/Kind,System.Delegate)", (const void *)PD_AddMethodIntern); mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Atom)", (const void *)PD_SendAtom); - mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.AtomList)", (const void *)PD_SendAnything); - mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.Atom[])", (const void *)PD_SendAnything2); + mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.Atom[])", (const void *)PD_SendAnything); mono_add_internal_call("PureData.External::SendEx(PureData.Symbol,object)", (const void *)PD_SendObject); - // load important classes - clr_symbol = mono_class_from_name(image,"PureData","Symbol"); - assert(clr_symbol); - clr_pointer = mono_class_from_name(image,"PureData","Pointer"); - assert(clr_pointer); - clr_atom = mono_class_from_name(image,"PureData","Atom"); - assert(clr_atom); - clr_atomlist = mono_class_from_name(image,"PureData","AtomList"); - assert(clr_atomlist); - clr_external = mono_class_from_name(image,"PureData","External"); - assert(clr_external); - - clr_desc_tostring = mono_method_desc_new("::ToString()",FALSE); - assert(clr_desc_tostring); - clr_desc_ctor = mono_method_desc_new("::.ctor(AtomList)",FALSE); - assert(clr_desc_ctor); - - MonoMethodDesc *desc = mono_method_desc_new("System.Reflection.MethodBase:Invoke(object,object[])",FALSE); - clr_meth_invoke = mono_method_desc_search_in_image(desc,mono_get_corlib()); - - MonoClass *delegate = mono_class_from_name(mono_get_corlib(),"System","Delegate"); - assert(delegate); - clr_prop_method = mono_class_get_property_from_name(delegate,"Method"); - assert(clr_prop_method); - - // static objects to avoid allocation at method call time - clr_objarr_1 = mono_array_new(monodomain,mono_get_object_class(),1); - clr_objarr_2 = mono_array_new(monodomain,mono_get_object_class(),2); - clr_objarr_3 = mono_array_new(monodomain,mono_get_object_class(),3); - clr_obj_int = mono_object_new(monodomain,mono_get_int32_class()); - clr_obj_single = mono_object_new(monodomain,mono_get_single_class()); - clr_obj_symbol = mono_object_new(monodomain,clr_symbol); - clr_obj_pointer = mono_object_new(monodomain,clr_pointer); - clr_obj_atomlist = mono_object_new(monodomain,clr_atomlist); - // unboxed addresses - clr_val_int = (int *)mono_object_unbox(clr_obj_int); - clr_val_single = (float *)mono_object_unbox(clr_obj_single); - clr_val_symbol = (t_symbol **)mono_object_unbox(clr_obj_symbol); - clr_val_pointer = (void **)mono_object_unbox(clr_obj_pointer); - clr_val_atomlist = (AtomList *)mono_object_unbox(clr_obj_atomlist); + + /////////////////////////////////////////////////////////// // make proxy class proxy_class = class_new(gensym("clr proxy"),NULL,NULL,sizeof(t_proxy),CLASS_PD|CLASS_NOINLET,A_NULL); @@ -1032,8 +672,31 @@ void clr_setup(void) // install loader hook sys_register_loader(classloader); - // ready! - post("CLR extension - (c)2006 Davide Morelli, Thomas Grill"); + /////////////////////////////////////////////////////////// + + // call static Class::Setup function + MonoClass *clr_class = mono_class_from_name(image,"PureData","Class"); + assert(clr_class); + MonoMethodDesc *desc = mono_method_desc_new("::Setup()",FALSE); + MonoMethod *setup = mono_method_desc_search_in_class(desc,clr_class); + + MonoObject *exc; + mono_runtime_invoke(setup,NULL,NULL,&exc); + if(exc) + post("CLR - setup function failed"); + else { + // ready! + post("CLR extension - (c)2006 Davide Morelli, Thomas Grill"); + } + + // necessary data should have been set by Setup + MonoClass *clr_internal = mono_class_from_name(image,"PureData","Internal"); + assert(clr_internal); + MonoVTable *clr_internal_vt = mono_class_vtable(monodomain,clr_internal); + MonoClassField *fld = mono_class_get_field_from_name (clr_internal,"pass"); + assert(fld); + mono_field_static_get_value(clr_internal_vt,fld,&clr_pass); + assert(clr_pass); } else error("clr: mono domain couldn't be initialized!"); diff --git a/test/test-help.pd b/test/test-help.pd index 26246c4..a931342 100644 --- a/test/test-help.pd +++ b/test/test-help.pd @@ -1,4 +1,4 @@ -#N canvas 617 153 862 841 12; +#N canvas 617 153 866 845 12; #X floatatom 125 51 5 0 0 0 - - -; #X symbolatom 320 81 10 0 0 0 - - -; #X msg 536 45 msg one 2 three; @@ -20,8 +20,6 @@ #X msg 289 197 send \$1 b c; #X obj 407 497 print RECV1; #X obj 406 463 r receiver; -#X obj 554 465 r receiver2; -#X obj 555 499 print RECV2; #X floatatom 526 362 5 0 0 0 - - -; #X symbolatom 578 364 10 0 0 0 - - -; #X text 585 318 passive - bang to see; @@ -38,34 +36,33 @@ #X obj 141 650 print A; #X obj 138 725 print B; #X msg 120 580 trigger; -#X connect 0 0 30 0; -#X connect 1 0 30 0; -#X connect 2 0 30 0; +#X connect 0 0 28 0; +#X connect 1 0 28 0; +#X connect 2 0 28 0; #X connect 3 0 8 0; #X connect 4 0 5 0; -#X connect 5 0 30 0; +#X connect 5 0 28 0; #X connect 6 0 1 0; #X connect 7 0 1 0; -#X connect 8 0 30 0; -#X connect 9 0 30 0; -#X connect 10 0 30 0; -#X connect 11 0 30 0; -#X connect 12 0 30 0; -#X connect 13 0 30 1; -#X connect 15 0 30 2; +#X connect 8 0 28 0; +#X connect 9 0 28 0; +#X connect 10 0 28 0; +#X connect 11 0 28 0; +#X connect 12 0 28 0; +#X connect 13 0 28 1; +#X connect 15 0 28 2; #X connect 16 0 17 0; -#X connect 17 0 30 0; +#X connect 17 0 28 0; #X connect 19 0 18 0; -#X connect 20 0 21 0; -#X connect 22 0 30 3; -#X connect 23 0 30 3; -#X connect 26 0 30 3; -#X connect 27 0 30 1; -#X connect 28 0 30 3; -#X connect 29 0 30 1; -#X connect 30 0 14 0; -#X connect 31 0 30 3; -#X connect 32 0 33 0; -#X connect 32 0 34 0; -#X connect 33 0 35 0; -#X connect 36 0 32 0; +#X connect 20 0 28 3; +#X connect 21 0 28 3; +#X connect 24 0 28 3; +#X connect 25 0 28 1; +#X connect 26 0 28 3; +#X connect 27 0 28 1; +#X connect 28 0 14 0; +#X connect 29 0 28 3; +#X connect 30 0 31 0; +#X connect 30 0 32 0; +#X connect 31 0 33 0; +#X connect 34 0 30 0; diff --git a/test/test.cs b/test/test.cs index beac897..cdb7ba7 100644 --- a/test/test.cs +++ b/test/test.cs @@ -1,18 +1,22 @@ using System; +using Timing; +using PureData; public class test: - PureData.External + External { - PureData.Atom[] args; - + Atom[] args; float farg; - public test(PureData.AtomList args) + // necessary (for now...) + public test() {} + + public test(Atom[] args) { Post("Test.ctor "+args.ToString()); - // that's the way to store args (don't just copy an AtomList instance!!) - this.args = (PureData.Atom[])args; + // save args + this.args = args; // AddInlet(s_list,new PureData.Symbol("list2")); AddInlet(); @@ -25,23 +29,23 @@ public class test: // returns void or ClassType private static ClassType Setup(test obj) { - AddMethod(0,new Method(obj.MyBang)); - AddMethod(0,new MethodFloat(obj.MyFloat)); - AddMethod(0,new MethodSymbol(obj.MySymbol)); - AddMethod(0,new MethodList(obj.MyList)); - AddMethod(0,"set",new MethodAnything(obj.MySet)); - AddMethod(0,"send",new MethodAnything(obj.MySend)); - AddMethod(0,"trigger",new Method(obj.MyTrigger)); - AddMethod(0,new MethodObject(obj.MyObject)); - AddMethod(0,new MethodAnything(obj.MyAnything)); - AddMethod(1,new MethodFloat(obj.MyFloat1)); - AddMethod(1,new MethodAnything(obj.MyAny1)); - - Post("Test.Main"); +// Post("Test.Setup"); + + AddMethod(obj.bang); + AddMethod(obj.MyFloat); + AddMethod(obj.symbol); + AddMethod(obj.list); + AddMethod(0,"set",obj.set); + AddMethod(0,"send",obj.send); + AddMethod(0,"trigger",obj.trigger); + AddMethod(0,obj.MyObject); + AddMethod(0,obj.MyAnything); + AddMethod(1,obj.MyFloat1); + AddMethod(1,obj.MyAny1); return ClassType.Default; } - protected virtual void MyBang() + protected void bang() { Post("Test-BANG "+farg.ToString()); Outlet(0); @@ -58,36 +62,35 @@ public class test: Post("Test-FLOAT1 "+f.ToString()); } - protected virtual void MyAny1(int ix,PureData.Symbol s,PureData.AtomList l) + protected virtual void MyAny1(int ix,Symbol s,Atom[] l) { Post(ix.ToString()+": Test-ANY1 "+l.ToString()); } - protected virtual void MySymbol(PureData.Symbol s) + protected virtual void symbol(Symbol s) { Post("Test-SYMBOL "+s.ToString()); Outlet(0,s); } - protected virtual void MyList(PureData.AtomList l) + protected virtual void list(Atom[] l) { Post("Test-LIST "+l.ToString()); Outlet(0,l); } - protected virtual void MySet(int ix,PureData.Symbol s,PureData.AtomList l) + protected virtual void set(int ix,Symbol s,Atom[] l) { Post("Test-SET "+l.ToString()); - Outlet(0,new PureData.Symbol("set"),l); + Outlet(0,new Symbol("set"),l); } - protected virtual void MySend(int ix,PureData.Symbol s,PureData.AtomList l) + protected virtual void send(int ix,Symbol s,Atom[] l) { - Send(new PureData.Symbol("receiver"),l); - Send(new PureData.Symbol("receiver2"),(PureData.Atom[])l); + Send(new Symbol("receiver"),l); } - protected virtual void MyTrigger() + protected virtual void trigger() { OutletEx(0,"hey"); } @@ -98,7 +101,7 @@ public class test: OutletEx(0,obj); } - protected virtual void MyAnything(int ix,PureData.Symbol s,PureData.AtomList l) + protected virtual void MyAnything(int ix,Symbol s,Atom[] l) { Post(ix.ToString()+": Test-("+s.ToString()+") "+l.ToString()); Outlet(0,s,l); diff --git a/test/test.csproj b/test/test.csproj index d4f4e7d..1b2d888 100644 --- a/test/test.csproj +++ b/test/test.csproj @@ -1,105 +1,112 @@ -<VisualStudioProject> - <CSHARP - ProjectType = "Local" - ProductVersion = "7.10.3077" - SchemaVersion = "2.0" - ProjectGuid = "{6CED2448-6407-4AF7-95B6-932D8118AF3D}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "Test" - AssemblyOriginatorKeyFile = "" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "Library" - PreBuildEvent = "" - PostBuildEvent = "" - RootNamespace = "Test" - RunPostBuildEvent = "OnBuildSuccess" - StartupObject = "" - > - <Config - Name = "Debug" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "DEBUG;TRACE" - DocumentationFile = "" - DebugSymbols = "true" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "false" - OutputPath = "bin\Debug\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - <Config - Name = "Release" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "TRACE" - DocumentationFile = "" - DebugSymbols = "false" - FileAlignment = "4096" - IncrementalBuild = "false" - NoStdLib = "false" - NoWarn = "" - Optimize = "true" - OutputPath = "bin\Release\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.XML" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" - /> - <Reference - Name = "PureData" - Project = "{0015D5E7-B0FB-4F06-B334-225447D1F992}" - Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" - /> - </References> - </Build> - <Files> - <Include> - <File - RelPath = "AssemblyInfo.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File - RelPath = "test.cs" - SubType = "Code" - BuildAction = "Compile" - /> - </Include> - </Files> - </CSHARP> -</VisualStudioProject> - +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectType>Local</ProjectType> + <ProductVersion>8.0.50727</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{6CED2448-6407-4AF7-95B6-932D8118AF3D}</ProjectGuid> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ApplicationIcon> + </ApplicationIcon> + <AssemblyKeyContainerName> + </AssemblyKeyContainerName> + <AssemblyName>Test</AssemblyName> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + <DefaultClientScript>JScript</DefaultClientScript> + <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout> + <DefaultTargetSchema>IE50</DefaultTargetSchema> + <DelaySign>false</DelaySign> + <OutputType>Library</OutputType> + <RootNamespace>Test</RootNamespace> + <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> + <StartupObject> + </StartupObject> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <OutputPath>bin\Debug\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>true</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>full</DebugType> + <ErrorReport>prompt</ErrorReport> + <UseVSHostingProcess>true</UseVSHostingProcess> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <OutputPath>bin\debug\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>false</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>none</DebugType> + <ErrorReport>prompt</ErrorReport> + <UseVSHostingProcess>true</UseVSHostingProcess> + </PropertyGroup> + <ItemGroup> + <Reference Include="System"> + <Name>System</Name> + </Reference> + <Reference Include="System.Data"> + <Name>System.Data</Name> + </Reference> + <Reference Include="System.Xml"> + <Name>System.XML</Name> + </Reference> + <ProjectReference Include="..\PureData\PureData.csproj"> + <Name>PureData</Name> + <Project>{0015D5E7-B0FB-4F06-B334-225447D1F992}</Project> + <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Compile Include="AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="test.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="timing.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent> + </PreBuildEvent> + <PostBuildEvent> + </PostBuildEvent> + </PropertyGroup> +</Project>
\ No newline at end of file |