aboutsummaryrefslogtreecommitdiff
path: root/PureData/DynamicMethod.cs
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2006-04-18 01:38:08 +0000
committerThomas Grill <xovo@users.sourceforge.net>2006-04-18 01:38:08 +0000
commited0031b621c6cf8824a9a3e588426907244aeb7e (patch)
treea797d5ee35b65b43f970f331cdee940d7aaced32 /PureData/DynamicMethod.cs
parent4e7353f45954a8a5d9aaa3dd40eed3f9f62c2062 (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
Diffstat (limited to 'PureData/DynamicMethod.cs')
-rw-r--r--PureData/DynamicMethod.cs101
1 files changed, 101 insertions, 0 deletions
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
+ }
+}