123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Threading;
- namespace LuaInterface
- {
- /*
- * Structure to store a type and the return types of
- * its methods (the type of the returned value and out/ref
- * parameters).
- */
- struct LuaClassType
- {
- public Type klass;
- public Type[][] returnTypes;
- }
- /*
- * Common interface for types generated from tables. The method
- * returns the table that overrides some or all of the type's methods.
- */
- public interface ILuaGeneratedType
- {
- LuaTable __luaInterface_getLuaTable();
- }
- /*
- * Class used for generating delegates that get a function from the Lua
- * stack as a delegate of a specific type.
- *
- * Author: Fabio Mascarenhas
- * Version: 1.0
- */
- class DelegateGenerator
- {
- private ObjectTranslator translator;
- private Type delegateType;
- public DelegateGenerator(ObjectTranslator translator,Type delegateType)
- {
- this.translator=translator;
- this.delegateType=delegateType;
- }
- public object extractGenerated(IntPtr luaState,int stackPos)
- {
- return CodeGeneration.Instance.GetDelegate(delegateType,translator.getFunction(luaState,stackPos));
- }
- }
- /*
- * Class used for generating delegates that get a table from the Lua
- * stack as a an object of a specific type.
- *
- * Author: Fabio Mascarenhas
- * Version: 1.0
- */
- class ClassGenerator
- {
- private ObjectTranslator translator;
- private Type klass;
- public ClassGenerator(ObjectTranslator translator,Type klass)
- {
- this.translator=translator;
- this.klass=klass;
- }
- public object extractGenerated(IntPtr luaState,int stackPos)
- {
- return CodeGeneration.Instance.GetClassInstance(klass,translator.getTable(luaState,stackPos));
- }
- }
- /*
- * Dynamically generates new types from existing types and
- * Lua function and table values. Generated types are event handlers,
- * delegates, interface implementations and subclasses.
- *
- * Author: Fabio Mascarenhas
- * Version: 1.0
- */
- class CodeGeneration
- {
- private Type eventHandlerParent=typeof(LuaEventHandler);
- private Dictionary<Type, Type> eventHandlerCollection=new Dictionary<Type, Type>();
- private Type delegateParent=typeof(LuaDelegate);
- private Dictionary<Type, Type> delegateCollection=new Dictionary<Type, Type>();
- private Type classHelper=typeof(LuaClassHelper);
- private Dictionary<Type, LuaClassType> classCollection=new Dictionary<Type, LuaClassType>();
- private AssemblyName assemblyName;
- private AssemblyBuilder newAssembly;
- private ModuleBuilder newModule;
- private int luaClassNumber=1;
- private static readonly CodeGeneration instance = new CodeGeneration();
- static CodeGeneration()
- {
- }
- private CodeGeneration()
- {
- // Create an assembly name
- assemblyName=new AssemblyName( );
- assemblyName.Name="LuaInterface_generatedcode";
- // Create a new assembly with one module.
- newAssembly=Thread.GetDomain().DefineDynamicAssembly(
- assemblyName, AssemblyBuilderAccess.Run);
- newModule=newAssembly.DefineDynamicModule("LuaInterface_generatedcode");
- }
- /*
- * Singleton instance of the class
- */
- public static CodeGeneration Instance
- {
- get
- {
- return instance;
- }
- }
- /*
- * Generates an event handler that calls a Lua function
- */
- private Type GenerateEvent(Type eventHandlerType)
- {
- string typeName;
- lock(this)
- {
- typeName = "LuaGeneratedClass" + luaClassNumber;
- luaClassNumber++;
- }
- // Define a public class in the assembly, called typeName
- TypeBuilder myType=newModule.DefineType(typeName,TypeAttributes.Public,eventHandlerParent);
- // Defines the handler method. Its signature is void(object,<subclassofEventArgs>)
- Type[] paramTypes = new Type[2];
- paramTypes[0]=typeof(object);
- paramTypes[1]=eventHandlerType;
- Type returnType=typeof(void);
- MethodBuilder handleMethod=myType.DefineMethod("HandleEvent",
- MethodAttributes.Public|MethodAttributes.HideBySig,
- returnType,paramTypes);
- // Emits the IL for the method. It loads the arguments
- // and calls the handleEvent method of the base class
- ILGenerator generator=handleMethod.GetILGenerator( );
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldarg_1);
- generator.Emit(OpCodes.Ldarg_2);
- MethodInfo miGenericEventHandler;
- miGenericEventHandler=eventHandlerParent.GetMethod("handleEvent");
- generator.Emit(OpCodes.Call,miGenericEventHandler);
- // returns
- generator.Emit(OpCodes.Ret);
- // creates the new type
- return myType.CreateType();
- }
- /*
- * Generates a type that can be used for instantiating a delegate
- * of the provided type, given a Lua function.
- */
- private Type GenerateDelegate(Type delegateType)
- {
- string typeName;
- lock(this)
- {
- typeName = "LuaGeneratedClass" + luaClassNumber;
- luaClassNumber++;
- }
- // Define a public class in the assembly, called typeName
- TypeBuilder myType=newModule.DefineType(typeName,TypeAttributes.Public,delegateParent);
- // Defines the delegate method with the same signature as the
- // Invoke method of delegateType
- MethodInfo invokeMethod=delegateType.GetMethod("Invoke");
- ParameterInfo[] paramInfo=invokeMethod.GetParameters();
- Type[] paramTypes=new Type[paramInfo.Length];
- Type returnType=invokeMethod.ReturnType;
- // Counts out and ref params, for use later
- int nOutParams=0; int nOutAndRefParams=0;
- for(int i=0;i<paramTypes.Length;i++)
- {
- paramTypes[i]=paramInfo[i].ParameterType;
- if((!paramInfo[i].IsIn) && paramInfo[i].IsOut)
- nOutParams++;
- if(paramTypes[i].IsByRef)
- nOutAndRefParams++;
- }
- int[] refArgs=new int[nOutAndRefParams];
- MethodBuilder delegateMethod=myType.DefineMethod("CallFunction",
- invokeMethod.Attributes,
- returnType,paramTypes);
- // Generates the IL for the method
- ILGenerator generator=delegateMethod.GetILGenerator( );
- generator.DeclareLocal(typeof(object[])); // original arguments
- generator.DeclareLocal(typeof(object[])); // with out-only arguments removed
- generator.DeclareLocal(typeof(int[])); // indexes of out and ref arguments
- if(!(returnType == typeof(void))) // return value
- generator.DeclareLocal(returnType);
- else
- generator.DeclareLocal(typeof(object));
- // Initializes local variables
- generator.Emit(OpCodes.Ldc_I4,paramTypes.Length);
- generator.Emit(OpCodes.Newarr,typeof(object));
- generator.Emit(OpCodes.Stloc_0);
- generator.Emit(OpCodes.Ldc_I4,paramTypes.Length-nOutParams);
- generator.Emit(OpCodes.Newarr,typeof(object));
- generator.Emit(OpCodes.Stloc_1);
- generator.Emit(OpCodes.Ldc_I4,nOutAndRefParams);
- generator.Emit(OpCodes.Newarr,typeof(int));
- generator.Emit(OpCodes.Stloc_2);
- // Stores the arguments in the local variables
- for(int iArgs=0,iInArgs=0,iOutArgs=0;iArgs<paramTypes.Length;iArgs++)
- {
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldc_I4,iArgs);
- generator.Emit(OpCodes.Ldarg,iArgs+1);
- if(paramTypes[iArgs].IsByRef)
- {
- if(paramTypes[iArgs].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
- generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
- } else generator.Emit(OpCodes.Ldind_Ref);
- }
- else
- {
- if(paramTypes[iArgs].IsValueType)
- generator.Emit(OpCodes.Box,paramTypes[iArgs]);
- }
- generator.Emit(OpCodes.Stelem_Ref);
- if(paramTypes[iArgs].IsByRef)
- {
- generator.Emit(OpCodes.Ldloc_2);
- generator.Emit(OpCodes.Ldc_I4,iOutArgs);
- generator.Emit(OpCodes.Ldc_I4,iArgs);
- generator.Emit(OpCodes.Stelem_I4);
- refArgs[iOutArgs]=iArgs;
- iOutArgs++;
- }
- if(paramInfo[iArgs].IsIn || (!paramInfo[iArgs].IsOut))
- {
- generator.Emit(OpCodes.Ldloc_1);
- generator.Emit(OpCodes.Ldc_I4,iInArgs);
- generator.Emit(OpCodes.Ldarg,iArgs+1);
- if(paramTypes[iArgs].IsByRef)
- {
- if(paramTypes[iArgs].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
- generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
- }
- else generator.Emit(OpCodes.Ldind_Ref);
- }
- else
- {
- if(paramTypes[iArgs].IsValueType)
- generator.Emit(OpCodes.Box,paramTypes[iArgs]);
- }
- generator.Emit(OpCodes.Stelem_Ref);
- iInArgs++;
- }
- }
- // Calls the callFunction method of the base class
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldloc_1);
- generator.Emit(OpCodes.Ldloc_2);
- MethodInfo miGenericEventHandler;
- miGenericEventHandler=delegateParent.GetMethod("callFunction");
- generator.Emit(OpCodes.Call,miGenericEventHandler);
- // Stores return value
- if(returnType == typeof(void))
- {
- generator.Emit(OpCodes.Pop);
- generator.Emit(OpCodes.Ldnull);
- }
- else if(returnType.IsValueType)
- {
- generator.Emit(OpCodes.Unbox,returnType);
- generator.Emit(OpCodes.Ldobj,returnType);
- } else generator.Emit(OpCodes.Castclass,returnType);
- generator.Emit(OpCodes.Stloc_3);
- // Stores new value of out and ref params
- for(int i=0;i<refArgs.Length;i++)
- {
- generator.Emit(OpCodes.Ldarg,refArgs[i]+1);
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldc_I4,refArgs[i]);
- generator.Emit(OpCodes.Ldelem_Ref);
- if(paramTypes[refArgs[i]].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Unbox,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Ldobj,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Stobj,paramTypes[refArgs[i]].GetElementType());
- }
- else
- {
- generator.Emit(OpCodes.Castclass,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Stind_Ref);
- }
- }
- // Returns
- if(!(returnType == typeof(void)))
- generator.Emit(OpCodes.Ldloc_3);
- generator.Emit(OpCodes.Ret);
- // creates the new type
- return myType.CreateType();
- }
- /*
- * Generates an implementation of klass, if it is an interface, or
- * a subclass of klass that delegates its virtual methods to a Lua table.
- */
- public void GenerateClass(Type klass,out Type newType,out Type[][] returnTypes, LuaTable luaTable)
- {
- string typeName;
- lock(this)
- {
- typeName = "LuaGeneratedClass" + luaClassNumber;
- luaClassNumber++;
- }
- TypeBuilder myType;
- // Define a public class in the assembly, called typeName
- if(klass.IsInterface)
- myType=newModule.DefineType(typeName,TypeAttributes.Public,typeof(object),new Type[] { klass,typeof(ILuaGeneratedType) });
- else
- myType=newModule.DefineType(typeName,TypeAttributes.Public,klass,new Type[] { typeof(ILuaGeneratedType) });
- // Field that stores the Lua table
- FieldBuilder luaTableField=myType.DefineField("__luaInterface_luaTable",typeof(LuaTable),FieldAttributes.Public);
- // Field that stores the return types array
- FieldBuilder returnTypesField=myType.DefineField("__luaInterface_returnTypes",typeof(Type[][]),FieldAttributes.Public);
- // Generates the constructor for the new type, it takes a Lua table and an array
- // of return types and stores them in the respective fields
- ConstructorBuilder constructor=
- myType.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,new Type[] { typeof(LuaTable),typeof(Type[][]) });
- ILGenerator generator=constructor.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- if(klass.IsInterface)
- generator.Emit(OpCodes.Call,typeof(object).GetConstructor(Type.EmptyTypes));
- else
- generator.Emit(OpCodes.Call,klass.GetConstructor(Type.EmptyTypes));
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldarg_1);
- generator.Emit(OpCodes.Stfld,luaTableField);
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldarg_2);
- generator.Emit(OpCodes.Stfld,returnTypesField);
- generator.Emit(OpCodes.Ret);
- // Generates overriden versions of the klass' public and protected virtual methods that have been explicitly specfied
- BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
- MethodInfo[] classMethods=klass.GetMethods(flags);
- returnTypes=new Type[classMethods.Length][];
- int i=0;
- foreach(MethodInfo method in classMethods)
- {
- if(klass.IsInterface)
- {
- GenerateMethod(myType,method,
- MethodAttributes.HideBySig|MethodAttributes.Virtual|MethodAttributes.NewSlot,
- i,luaTableField,returnTypesField,false,out returnTypes[i]);
- i++;
- }
- else
- {
- if(!method.IsPrivate && !method.IsFinal && method.IsVirtual)
- {
- if (luaTable[method.Name] != null) {
- GenerateMethod(myType,method,(method.Attributes|MethodAttributes.NewSlot)^MethodAttributes.NewSlot,i,
- luaTableField,returnTypesField,true,out returnTypes[i]);
- i++;
- }
- }
- }
- }
- // Generates an implementation of the __luaInterface_getLuaTable method
- MethodBuilder returnTableMethod=myType.DefineMethod("__luaInterface_getLuaTable",
- MethodAttributes.Public|MethodAttributes.HideBySig|MethodAttributes.Virtual,
- typeof(LuaTable),new Type[0]);
- myType.DefineMethodOverride(returnTableMethod,typeof(ILuaGeneratedType).GetMethod("__luaInterface_getLuaTable"));
- generator=returnTableMethod.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld,luaTableField);
- generator.Emit(OpCodes.Ret);
- // Creates the type
- newType=myType.CreateType();
- }
- /*
- * Generates an overriden implementation of method inside myType that delegates
- * to a function in a Lua table with the same name, if the function exists. If it
- * doesn't the method calls the base method (or does nothing, in case of interface
- * implementations).
- */
- private void GenerateMethod(TypeBuilder myType,MethodInfo method,MethodAttributes attributes,
- int methodIndex,FieldInfo luaTableField,FieldInfo returnTypesField,bool generateBase,out Type[] returnTypes)
- {
- ParameterInfo[] paramInfo=method.GetParameters();
- Type[] paramTypes=new Type[paramInfo.Length];
- List<Type> returnTypesList=new List<Type>();
- // Counts out and ref parameters, for later use,
- // and creates the list of return types
- int nOutParams=0; int nOutAndRefParams=0;
- Type returnType=method.ReturnType;
- returnTypesList.Add(returnType);
- for(int i=0;i<paramTypes.Length;i++)
- {
- paramTypes[i]=paramInfo[i].ParameterType;
- if((!paramInfo[i].IsIn) && paramInfo[i].IsOut)
- nOutParams++;
- if(paramTypes[i].IsByRef)
- {
- returnTypesList.Add(paramTypes[i].GetElementType());
- nOutAndRefParams++;
- }
- }
- int[] refArgs=new int[nOutAndRefParams];
- returnTypes=returnTypesList.ToArray();
- // Generates a version of the method that calls the base implementation
- // directly, for use by the base field of the table
- if(generateBase)
- {
- String baseName = "__luaInterface_base_"+method.Name;
- MethodBuilder baseMethod=myType.DefineMethod(baseName,
- MethodAttributes.Public|MethodAttributes.NewSlot|MethodAttributes.HideBySig,
- returnType,paramTypes);
- ILGenerator generatorBase=baseMethod.GetILGenerator();
- generatorBase.Emit(OpCodes.Ldarg_0);
- for(int i=0;i<paramTypes.Length;i++)
- generatorBase.Emit(OpCodes.Ldarg,i+1);
- generatorBase.Emit(OpCodes.Call,method);
- //if (returnType == typeof(void))
- // generatorBase.Emit(OpCodes.Pop);
- generatorBase.Emit(OpCodes.Ret);
- }
- // Defines the method
- MethodBuilder methodImpl=myType.DefineMethod(method.Name,attributes,
- returnType,paramTypes);
- // If it's an implementation of an interface tells what method it
- // is overriding
- if(myType.BaseType.Equals(typeof(object)))
- myType.DefineMethodOverride(methodImpl,method);
- ILGenerator generator=methodImpl.GetILGenerator( );
- generator.DeclareLocal(typeof(object[])); // original arguments
- generator.DeclareLocal(typeof(object[])); // with out-only arguments removed
- generator.DeclareLocal(typeof(int[])); // indexes of out and ref arguments
- if(!(returnType == typeof(void))) // return value
- generator.DeclareLocal(returnType);
- else
- generator.DeclareLocal(typeof(object));
- // Initializes local variables
- generator.Emit(OpCodes.Ldc_I4,paramTypes.Length);
- generator.Emit(OpCodes.Newarr,typeof(object));
- generator.Emit(OpCodes.Stloc_0);
- generator.Emit(OpCodes.Ldc_I4,paramTypes.Length-nOutParams+1);
- generator.Emit(OpCodes.Newarr,typeof(object));
- generator.Emit(OpCodes.Stloc_1);
- generator.Emit(OpCodes.Ldc_I4,nOutAndRefParams);
- generator.Emit(OpCodes.Newarr,typeof(int));
- generator.Emit(OpCodes.Stloc_2);
- generator.Emit(OpCodes.Ldloc_1);
- generator.Emit(OpCodes.Ldc_I4_0);
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld,luaTableField);
- generator.Emit(OpCodes.Stelem_Ref);
- // Stores the arguments into the local variables, as needed
- for(int iArgs=0,iInArgs=1,iOutArgs=0;iArgs<paramTypes.Length;iArgs++)
- {
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldc_I4,iArgs);
- generator.Emit(OpCodes.Ldarg,iArgs+1);
- if(paramTypes[iArgs].IsByRef)
- {
- if(paramTypes[iArgs].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
- generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
- }
- else generator.Emit(OpCodes.Ldind_Ref);
- }
- else
- {
- if(paramTypes[iArgs].IsValueType)
- generator.Emit(OpCodes.Box,paramTypes[iArgs]);
- }
- generator.Emit(OpCodes.Stelem_Ref);
- if(paramTypes[iArgs].IsByRef)
- {
- generator.Emit(OpCodes.Ldloc_2);
- generator.Emit(OpCodes.Ldc_I4,iOutArgs);
- generator.Emit(OpCodes.Ldc_I4,iArgs);
- generator.Emit(OpCodes.Stelem_I4);
- refArgs[iOutArgs]=iArgs;
- iOutArgs++;
- }
- if(paramInfo[iArgs].IsIn || (!paramInfo[iArgs].IsOut))
- {
- generator.Emit(OpCodes.Ldloc_1);
- generator.Emit(OpCodes.Ldc_I4,iInArgs);
- generator.Emit(OpCodes.Ldarg,iArgs+1);
- if(paramTypes[iArgs].IsByRef)
- {
- if(paramTypes[iArgs].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
- generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
- }
- else generator.Emit(OpCodes.Ldind_Ref);
- }
- else
- {
- if(paramTypes[iArgs].IsValueType)
- generator.Emit(OpCodes.Box,paramTypes[iArgs]);
- }
- generator.Emit(OpCodes.Stelem_Ref);
- iInArgs++;
- }
- }
- // Gets the function the method will delegate to by calling
- // the getTableFunction method of class LuaClassHelper
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld,luaTableField);
- generator.Emit(OpCodes.Ldstr,method.Name);
- generator.Emit(OpCodes.Call,classHelper.GetMethod("getTableFunction"));
- Label lab1=generator.DefineLabel();
- generator.Emit(OpCodes.Dup);
- generator.Emit(OpCodes.Brtrue_S,lab1);
- // Function does not exist, call base method
- generator.Emit(OpCodes.Pop);
- if(!method.IsAbstract)
- {
- generator.Emit(OpCodes.Ldarg_0);
- for(int i=0;i<paramTypes.Length;i++)
- generator.Emit(OpCodes.Ldarg,i+1);
- generator.Emit(OpCodes.Call,method);
- if(returnType == typeof(void))
- generator.Emit(OpCodes.Pop);
- generator.Emit(OpCodes.Ret);
- generator.Emit(OpCodes.Ldnull);
- } else
- generator.Emit(OpCodes.Ldnull);
- Label lab2=generator.DefineLabel();
- generator.Emit(OpCodes.Br_S,lab2);
- generator.MarkLabel(lab1);
- // Function exists, call using method callFunction of LuaClassHelper
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld,returnTypesField);
- generator.Emit(OpCodes.Ldc_I4,methodIndex);
- generator.Emit(OpCodes.Ldelem_Ref);
- generator.Emit(OpCodes.Ldloc_1);
- generator.Emit(OpCodes.Ldloc_2);
- generator.Emit(OpCodes.Call,classHelper.GetMethod("callFunction"));
- generator.MarkLabel(lab2);
- // Stores the function return value
- if(returnType == typeof(void))
- {
- generator.Emit(OpCodes.Pop);
- generator.Emit(OpCodes.Ldnull);
- }
- else if(returnType.IsValueType)
- {
- generator.Emit(OpCodes.Unbox,returnType);
- generator.Emit(OpCodes.Ldobj,returnType);
- }
- else generator.Emit(OpCodes.Castclass,returnType);
- generator.Emit(OpCodes.Stloc_3);
- // Sets return values of out and ref parameters
- for(int i=0;i<refArgs.Length;i++)
- {
- generator.Emit(OpCodes.Ldarg,refArgs[i]+1);
- generator.Emit(OpCodes.Ldloc_0);
- generator.Emit(OpCodes.Ldc_I4,refArgs[i]);
- generator.Emit(OpCodes.Ldelem_Ref);
- if(paramTypes[refArgs[i]].GetElementType().IsValueType)
- {
- generator.Emit(OpCodes.Unbox,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Ldobj,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Stobj,paramTypes[refArgs[i]].GetElementType());
- }
- else
- {
- generator.Emit(OpCodes.Castclass,paramTypes[refArgs[i]].GetElementType());
- generator.Emit(OpCodes.Stind_Ref);
- }
- }
- // Returns
- if(!(returnType == typeof(void)))
- generator.Emit(OpCodes.Ldloc_3);
- generator.Emit(OpCodes.Ret);
- }
- /*
- * Gets an event handler for the event type that delegates to the eventHandler Lua function.
- * Caches the generated type.
- */
- public LuaEventHandler GetEvent(Type eventHandlerType, LuaFunction eventHandler)
- {
- Type eventConsumerType;
- if (eventHandlerCollection.ContainsKey(eventHandlerType))
- {
- eventConsumerType=eventHandlerCollection[eventHandlerType];
- }
- else
- {
- eventConsumerType=GenerateEvent(eventHandlerType);
- eventHandlerCollection[eventHandlerType] = eventConsumerType;
- }
- LuaEventHandler luaEventHandler=(LuaEventHandler)Activator.CreateInstance(eventConsumerType);
- luaEventHandler.handler=eventHandler;
- return luaEventHandler;
- }
- /*
- * Gets a delegate with delegateType that calls the luaFunc Lua function
- * Caches the generated type.
- */
- public Delegate GetDelegate(Type delegateType, LuaFunction luaFunc)
- {
- List<Type> returnTypes=new List<Type>();
- Type luaDelegateType;
- if (delegateCollection.ContainsKey(delegateType))
- {
- luaDelegateType=delegateCollection[delegateType];
- }
- else
- {
- luaDelegateType=GenerateDelegate(delegateType);
- delegateCollection[delegateType] = luaDelegateType;
- }
- MethodInfo methodInfo=delegateType.GetMethod("Invoke");
- returnTypes.Add(methodInfo.ReturnType);
- foreach(ParameterInfo paramInfo in methodInfo.GetParameters())
- if(paramInfo.ParameterType.IsByRef)
- returnTypes.Add(paramInfo.ParameterType);
- LuaDelegate luaDelegate=(LuaDelegate)Activator.CreateInstance(luaDelegateType);
- luaDelegate.function=luaFunc;
- luaDelegate.returnTypes=returnTypes.ToArray();
- return Delegate.CreateDelegate(delegateType,luaDelegate,"CallFunction");
- }
- /*
- * Gets an instance of an implementation of the klass interface or
- * subclass of klass that delegates public virtual methods to the
- * luaTable table.
- * Caches the generated type.
- */
- public object GetClassInstance(Type klass, LuaTable luaTable)
- {
- LuaClassType luaClassType;
- if (classCollection.ContainsKey(klass))
- {
- luaClassType=classCollection[klass];
- }
- else
- {
- luaClassType=new LuaClassType();
- GenerateClass(klass,out luaClassType.klass,out luaClassType.returnTypes,luaTable);
- classCollection[klass] = luaClassType;
- }
- return Activator.CreateInstance(luaClassType.klass,new object[] {luaTable,luaClassType.returnTypes});
- }
- }
- }
|