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();
}