BizHawk/LuaInterface/LuaInterface/ObjectTranslator.cs

823 lines
27 KiB
C#

namespace LuaInterface
{
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
using Lua511;
/*
* Passes objects from the CLR to Lua and vice-versa
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class ObjectTranslator
{
internal CheckType typeChecker;
// object # to object (FIXME - it should be possible to get object address as an object #)
public readonly Dictionary<int, object> objects = new Dictionary<int, object>();
// object to object #
public readonly Dictionary<object, int> objectsBackMap = new Dictionary<object, int>();
internal Lua interpreter;
private MetaFunctions metaFunctions;
private List<Assembly> assemblies;
private LuaCSFunction registerTableFunction,unregisterTableFunction,getMethodSigFunction,
getConstructorSigFunction,importTypeFunction,loadAssemblyFunction;
internal EventHandlerContainer pendingEvents = new EventHandlerContainer();
public ObjectTranslator(Lua interpreter,IntPtr luaState)
{
this.interpreter=interpreter;
typeChecker=new CheckType(this);
metaFunctions=new MetaFunctions(this);
assemblies=new List<Assembly>();
importTypeFunction=new LuaCSFunction(this.importType);
loadAssemblyFunction=new LuaCSFunction(this.loadAssembly);
registerTableFunction=new LuaCSFunction(this.registerTable);
unregisterTableFunction=new LuaCSFunction(this.unregisterTable);
getMethodSigFunction=new LuaCSFunction(this.getMethodSignature);
getConstructorSigFunction=new LuaCSFunction(this.getConstructorSignature);
createLuaObjectList(luaState);
createIndexingMetaFunction(luaState);
createBaseClassMetatable(luaState);
createClassMetatable(luaState);
createFunctionMetatable(luaState);
setGlobalFunctions(luaState);
}
/*
* Sets up the list of objects in the Lua side
*/
private void createLuaObjectList(IntPtr luaState)
{
LuaDLL.lua_pushstring(luaState,"luaNet_objects");
LuaDLL.lua_newtable(luaState);
LuaDLL.lua_newtable(luaState);
LuaDLL.lua_pushstring(luaState,"__mode");
LuaDLL.lua_pushstring(luaState,"v");
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_setmetatable(luaState,-2);
LuaDLL.lua_settable(luaState, (int) LuaIndexes.LUA_REGISTRYINDEX);
}
/*
* Registers the indexing function of CLR objects
* passed to Lua
*/
private void createIndexingMetaFunction(IntPtr luaState)
{
LuaDLL.lua_pushstring(luaState,"luaNet_indexfunction");
LuaDLL.luaL_dostring(luaState,MetaFunctions.luaIndexFunction); // steffenj: lua_dostring renamed to luaL_dostring
//LuaDLL.lua_pushstdcallcfunction(luaState,indexFunction);
LuaDLL.lua_rawset(luaState, (int) LuaIndexes.LUA_REGISTRYINDEX);
}
/*
* Creates the metatable for superclasses (the base
* field of registered tables)
*/
private void createBaseClassMetatable(IntPtr luaState)
{
LuaDLL.luaL_newmetatable(luaState,"luaNet_searchbase");
LuaDLL.lua_pushstring(luaState,"__gc");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.gcFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__tostring");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.toStringFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__index");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.baseIndexFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__newindex");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.newindexFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_settop(luaState,-2);
}
/*
* Creates the metatable for type references
*/
private void createClassMetatable(IntPtr luaState)
{
LuaDLL.luaL_newmetatable(luaState,"luaNet_class");
LuaDLL.lua_pushstring(luaState,"__gc");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.gcFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__tostring");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.toStringFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__index");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.classIndexFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__newindex");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.classNewindexFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__call");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.callConstructorFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_settop(luaState,-2);
}
/*
* Registers the global functions used by LuaInterface
*/
private void setGlobalFunctions(IntPtr luaState)
{
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.indexFunction);
LuaDLL.lua_setglobal(luaState,"get_object_member");
LuaDLL.lua_pushstdcallcfunction(luaState,importTypeFunction);
LuaDLL.lua_setglobal(luaState,"import_type");
LuaDLL.lua_pushstdcallcfunction(luaState,loadAssemblyFunction);
LuaDLL.lua_setglobal(luaState,"load_assembly");
LuaDLL.lua_pushstdcallcfunction(luaState,registerTableFunction);
LuaDLL.lua_setglobal(luaState,"make_object");
LuaDLL.lua_pushstdcallcfunction(luaState,unregisterTableFunction);
LuaDLL.lua_setglobal(luaState,"free_object");
LuaDLL.lua_pushstdcallcfunction(luaState,getMethodSigFunction);
LuaDLL.lua_setglobal(luaState,"get_method_bysig");
LuaDLL.lua_pushstdcallcfunction(luaState,getConstructorSigFunction);
LuaDLL.lua_setglobal(luaState,"get_constructor_bysig");
}
/*
* Creates the metatable for delegates
*/
private void createFunctionMetatable(IntPtr luaState)
{
LuaDLL.luaL_newmetatable(luaState,"luaNet_function");
LuaDLL.lua_pushstring(luaState,"__gc");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.gcFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__call");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.execDelegateFunction);
LuaDLL.lua_settable(luaState,-3);
LuaDLL.lua_settop(luaState,-2);
}
/*
* Passes errors (argument e) to the Lua interpreter
*/
internal void throwError(IntPtr luaState, object e)
{
// We use this to remove anything pushed by luaL_where
int oldTop = LuaDLL.lua_gettop(luaState);
// Stack frame #1 is our C# wrapper, so not very interesting to the user
// Stack frame #2 must be the lua code that called us, so that's what we want to use
LuaDLL.luaL_where(luaState, 1);
object[] curlev = popValues(luaState, oldTop);
// Determine the position in the script where the exception was triggered
string errLocation = "";
if (curlev.Length > 0)
errLocation = curlev[0].ToString();
string message = e as string;
if (message != null)
{
// Wrap Lua error (just a string) and store the error location
e = new LuaScriptException(message, errLocation);
}
else
{
Exception ex = e as Exception;
if (ex != null)
{
// Wrap generic .NET exception as an InnerException and store the error location
e = new LuaScriptException(ex, errLocation);
}
}
push(luaState, e);
LuaDLL.lua_error(luaState);
}
/*
* Implementation of load_assembly. Throws an error
* if the assembly is not found.
*/
private int loadAssembly(IntPtr luaState)
{
try
{
string assemblyName=LuaDLL.lua_tostring(luaState,1);
Assembly assembly = null;
try
{
assembly = Assembly.LoadWithPartialName(assemblyName);
}
catch (BadImageFormatException)
{
// The assemblyName was invalid. It is most likely a path.
}
if (assembly == null)
{
assembly = Assembly.Load(AssemblyName.GetAssemblyName(assemblyName));
}
if (assembly != null && !assemblies.Contains(assembly))
{
assemblies.Add(assembly);
}
}
catch(Exception e)
{
throwError(luaState,e);
}
return 0;
}
internal Type FindType(string className)
{
foreach(Assembly assembly in assemblies)
{
Type klass=assembly.GetType(className);
if(klass!=null)
{
return klass;
}
}
return null;
}
/*
* Implementation of import_type. Returns nil if the
* type is not found.
*/
private int importType(IntPtr luaState)
{
string className=LuaDLL.lua_tostring(luaState,1);
Type klass=FindType(className);
if(klass!=null)
pushType(luaState,klass);
else
LuaDLL.lua_pushnil(luaState);
return 1;
}
/*
* Implementation of make_object. Registers a table (first
* argument in the stack) as an object subclassing the
* type passed as second argument in the stack.
*/
private int registerTable(IntPtr luaState)
{
if(LuaDLL.lua_type(luaState,1)==LuaTypes.LUA_TTABLE)
{
LuaTable luaTable=getTable(luaState,1);
string superclassName = LuaDLL.lua_tostring(luaState, 2);
if (superclassName != null)
{
Type klass = FindType(superclassName);
if (klass != null)
{
// Creates and pushes the object in the stack, setting
// it as the metatable of the first argument
object obj = CodeGeneration.Instance.GetClassInstance(klass, luaTable);
pushObject(luaState, obj, "luaNet_metatable");
LuaDLL.lua_newtable(luaState);
LuaDLL.lua_pushstring(luaState, "__index");
LuaDLL.lua_pushvalue(luaState, -3);
LuaDLL.lua_settable(luaState, -3);
LuaDLL.lua_pushstring(luaState, "__newindex");
LuaDLL.lua_pushvalue(luaState, -3);
LuaDLL.lua_settable(luaState, -3);
LuaDLL.lua_setmetatable(luaState, 1);
// Pushes the object again, this time as the base field
// of the table and with the luaNet_searchbase metatable
LuaDLL.lua_pushstring(luaState, "base");
int index = addObject(obj);
pushNewObject(luaState, obj, index, "luaNet_searchbase");
LuaDLL.lua_rawset(luaState, 1);
}
else
throwError(luaState, "register_table: can not find superclass '" + superclassName + "'");
}
else
throwError(luaState, "register_table: superclass name can not be null");
}
else throwError(luaState,"register_table: first arg is not a table");
return 0;
}
/*
* Implementation of free_object. Clears the metatable and the
* base field, freeing the created object for garbage-collection
*/
private int unregisterTable(IntPtr luaState)
{
try
{
if(LuaDLL.lua_getmetatable(luaState,1)!=0)
{
LuaDLL.lua_pushstring(luaState,"__index");
LuaDLL.lua_gettable(luaState,-2);
object obj=getRawNetObject(luaState,-1);
if(obj==null) throwError(luaState,"unregister_table: arg is not valid table");
FieldInfo luaTableField=obj.GetType().GetField("__luaInterface_luaTable");
if(luaTableField==null) throwError(luaState,"unregister_table: arg is not valid table");
luaTableField.SetValue(obj,null);
LuaDLL.lua_pushnil(luaState);
LuaDLL.lua_setmetatable(luaState,1);
LuaDLL.lua_pushstring(luaState,"base");
LuaDLL.lua_pushnil(luaState);
LuaDLL.lua_settable(luaState,1);
}
else throwError(luaState,"unregister_table: arg is not valid table");
}
catch(Exception e)
{
throwError(luaState,e.Message);
}
return 0;
}
/*
* Implementation of get_method_bysig. Returns nil
* if no matching method is not found.
*/
private int getMethodSignature(IntPtr luaState)
{
IReflect klass; object target;
int udata=LuaDLL.luanet_checkudata(luaState,1,"luaNet_class");
if(udata!=-1)
{
klass=(IReflect)objects[udata];
target=null;
}
else
{
target=getRawNetObject(luaState,1);
if(target==null)
{
throwError(luaState,"get_method_bysig: first arg is not type or object reference");
LuaDLL.lua_pushnil(luaState);
return 1;
}
klass=target.GetType();
}
string methodName=LuaDLL.lua_tostring(luaState,2);
Type[] signature=new Type[LuaDLL.lua_gettop(luaState)-2];
for(int i=0;i<signature.Length;i++)
signature[i]=FindType(LuaDLL.lua_tostring(luaState,i+3));
try
{
//CP: Added ignore case
MethodInfo method=klass.GetMethod(methodName,BindingFlags.Public | BindingFlags.Static |
BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase, null, signature, null);
pushFunction(luaState,new LuaCSFunction((new LuaMethodWrapper(this,target,klass,method)).call));
}
catch(Exception e)
{
throwError(luaState,e);
LuaDLL.lua_pushnil(luaState);
}
return 1;
}
/*
* Implementation of get_constructor_bysig. Returns nil
* if no matching constructor is found.
*/
private int getConstructorSignature(IntPtr luaState)
{
IReflect klass=null;
int udata=LuaDLL.luanet_checkudata(luaState,1,"luaNet_class");
if(udata!=-1)
{
klass=(IReflect)objects[udata];
}
if(klass==null)
{
throwError(luaState,"get_constructor_bysig: first arg is invalid type reference");
}
Type[] signature=new Type[LuaDLL.lua_gettop(luaState)-1];
for(int i=0;i<signature.Length;i++)
signature[i]=FindType(LuaDLL.lua_tostring(luaState,i+2));
try
{
ConstructorInfo constructor=klass.UnderlyingSystemType.GetConstructor(signature);
pushFunction(luaState,new LuaCSFunction((new LuaMethodWrapper(this,null,klass,constructor)).call));
}
catch(Exception e)
{
throwError(luaState,e);
LuaDLL.lua_pushnil(luaState);
}
return 1;
}
/*
* Pushes a type reference into the stack
*/
internal void pushType(IntPtr luaState, Type t)
{
pushObject(luaState,new ProxyType(t),"luaNet_class");
}
/*
* Pushes a delegate into the stack
*/
internal void pushFunction(IntPtr luaState, LuaCSFunction func)
{
pushObject(luaState,func,"luaNet_function");
}
/*
* Pushes a CLR object into the Lua stack as an userdata
* with the provided metatable
*/
internal void pushObject(IntPtr luaState, object o, string metatable)
{
int index = -1;
// Pushes nil
if(o==null)
{
LuaDLL.lua_pushnil(luaState);
return;
}
// Object already in the list of Lua objects? Push the stored reference.
bool found = objectsBackMap.TryGetValue(o, out index);
if(found)
{
LuaDLL.luaL_getmetatable(luaState,"luaNet_objects");
LuaDLL.lua_rawgeti(luaState,-1,index);
// Note: starting with lua5.1 the garbage collector may remove weak reference items (such as our luaNet_objects values) when the initial GC sweep
// occurs, but the actual call of the __gc finalizer for that object may not happen until a little while later. During that window we might call
// this routine and find the element missing from luaNet_objects, but collectObject() has not yet been called. In that case, we go ahead and call collect
// object here
// did we find a non nil object in our table? if not, we need to call collect object
LuaTypes type = LuaDLL.lua_type(luaState, -1);
if (type != LuaTypes.LUA_TNIL)
{
LuaDLL.lua_remove(luaState, -2); // drop the metatable - we're going to leave our object on the stack
return;
}
// MetaFunctions.dumpStack(this, luaState);
LuaDLL.lua_remove(luaState, -1); // remove the nil object value
LuaDLL.lua_remove(luaState, -1); // remove the metatable
collectObject(o, index); // Remove from both our tables and fall out to get a new ID
}
index = addObject(o);
pushNewObject(luaState,o,index,metatable);
}
/*
* Pushes a new object into the Lua stack with the provided
* metatable
*/
private void pushNewObject(IntPtr luaState,object o,int index,string metatable)
{
if(metatable=="luaNet_metatable")
{
// Gets or creates the metatable for the object's type
LuaDLL.luaL_getmetatable(luaState,o.GetType().AssemblyQualifiedName);
if(LuaDLL.lua_isnil(luaState,-1))
{
LuaDLL.lua_settop(luaState,-2);
LuaDLL.luaL_newmetatable(luaState,o.GetType().AssemblyQualifiedName);
LuaDLL.lua_pushstring(luaState,"cache");
LuaDLL.lua_newtable(luaState);
LuaDLL.lua_rawset(luaState,-3);
LuaDLL.lua_pushlightuserdata(luaState,LuaDLL.luanet_gettag());
LuaDLL.lua_pushnumber(luaState,1);
LuaDLL.lua_rawset(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__index");
LuaDLL.lua_pushstring(luaState,"luaNet_indexfunction");
LuaDLL.lua_rawget(luaState, (int) LuaIndexes.LUA_REGISTRYINDEX);
LuaDLL.lua_rawset(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__gc");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.gcFunction);
LuaDLL.lua_rawset(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__tostring");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.toStringFunction);
LuaDLL.lua_rawset(luaState,-3);
LuaDLL.lua_pushstring(luaState,"__newindex");
LuaDLL.lua_pushstdcallcfunction(luaState,metaFunctions.newindexFunction);
LuaDLL.lua_rawset(luaState,-3);
}
}
else
{
LuaDLL.luaL_getmetatable(luaState,metatable);
}
// Stores the object index in the Lua list and pushes the
// index into the Lua stack
LuaDLL.luaL_getmetatable(luaState,"luaNet_objects");
LuaDLL.luanet_newudata(luaState,index);
LuaDLL.lua_pushvalue(luaState,-3);
LuaDLL.lua_remove(luaState,-4);
LuaDLL.lua_setmetatable(luaState,-2);
LuaDLL.lua_pushvalue(luaState,-1);
LuaDLL.lua_rawseti(luaState,-3,index);
LuaDLL.lua_remove(luaState,-2);
}
/*
* Gets an object from the Lua stack with the desired type, if it matches, otherwise
* returns null.
*/
internal object getAsType(IntPtr luaState,int stackPos,Type paramType)
{
ExtractValue extractor=typeChecker.checkType(luaState,stackPos,paramType);
if(extractor!=null) return extractor(luaState,stackPos);
return null;
}
/// <summary>
/// Given the Lua int ID for an object remove it from our maps
/// </summary>
/// <param name="udata"></param>
internal void collectObject(int udata)
{
object o;
bool found = objects.TryGetValue(udata, out o);
// The other variant of collectObject might have gotten here first, in that case we will silently ignore the missing entry
if (found)
{
// Debug.WriteLine("Removing " + o.ToString() + " @ " + udata);
objects.Remove(udata);
objectsBackMap.Remove(o);
}
}
/// <summary>
/// Given an object reference, remove it from our maps
/// </summary>
/// <param name="udata"></param>
void collectObject(object o, int udata)
{
// Debug.WriteLine("Removing " + o.ToString() + " @ " + udata);
objects.Remove(udata);
objectsBackMap.Remove(o);
}
/// <summary>
/// We want to ensure that objects always have a unique ID
/// </summary>
int nextObj = 0;
int addObject(object obj)
{
// New object: inserts it in the list
int index = nextObj++;
// Debug.WriteLine("Adding " + obj.ToString() + " @ " + index);
objects[index] = obj;
objectsBackMap[obj] = index;
return index;
}
/*
* Gets an object from the Lua stack according to its Lua type.
*/
internal object getObject(IntPtr luaState,int index)
{
LuaTypes type=LuaDLL.lua_type(luaState,index);
switch(type)
{
case LuaTypes.LUA_TNUMBER:
{
return LuaDLL.lua_tonumber(luaState,index);
}
case LuaTypes.LUA_TSTRING:
{
return LuaDLL.lua_tostring(luaState,index);
}
case LuaTypes.LUA_TBOOLEAN:
{
return LuaDLL.lua_toboolean(luaState,index);
}
case LuaTypes.LUA_TTABLE:
{
return getTable(luaState,index);
}
case LuaTypes.LUA_TFUNCTION:
{
return getFunction(luaState,index);
}
case LuaTypes.LUA_TUSERDATA:
{
int udata=LuaDLL.luanet_tonetobject(luaState,index);
if(udata!=-1)
return objects[udata];
else
return getUserData(luaState,index);
}
default:
return null;
}
}
/*
* Gets the table in the index positon of the Lua stack.
*/
internal LuaTable getTable(IntPtr luaState,int index)
{
LuaDLL.lua_pushvalue(luaState,index);
return new LuaTable(LuaDLL.lua_ref(luaState,1),interpreter);
}
/*
* Gets the userdata in the index positon of the Lua stack.
*/
internal LuaUserData getUserData(IntPtr luaState,int index)
{
LuaDLL.lua_pushvalue(luaState,index);
return new LuaUserData(LuaDLL.lua_ref(luaState,1),interpreter);
}
/*
* Gets the function in the index positon of the Lua stack.
*/
internal LuaFunction getFunction(IntPtr luaState,int index)
{
LuaDLL.lua_pushvalue(luaState,index);
return new LuaFunction(LuaDLL.lua_ref(luaState,1),interpreter);
}
/*
* Gets the CLR object in the index positon of the Lua stack. Returns
* delegates as Lua functions.
*/
internal object getNetObject(IntPtr luaState,int index)
{
int idx=LuaDLL.luanet_tonetobject(luaState,index);
if(idx!=-1)
return objects[idx];
else
return null;
}
/*
* Gets the CLR object in the index positon of the Lua stack. Returns
* delegates as is.
*/
internal object getRawNetObject(IntPtr luaState,int index)
{
int udata=LuaDLL.luanet_rawnetobj(luaState,index);
if(udata!=-1)
{
return objects[udata];
}
return null;
}
/*
* Pushes the entire array into the Lua stack and returns the number
* of elements pushed.
*/
internal int returnValues(IntPtr luaState, object[] returnValues)
{
if(LuaDLL.lua_checkstack(luaState,returnValues.Length+5))
{
for(int i=0;i<returnValues.Length;i++)
{
push(luaState,returnValues[i]);
}
return returnValues.Length;
} else
return 0;
}
/*
* Gets the values from the provided index to
* the top of the stack and returns them in an array.
*/
internal object[] popValues(IntPtr luaState,int oldTop)
{
int newTop=LuaDLL.lua_gettop(luaState);
if(oldTop==newTop)
{
return null;
}
else
{
ArrayList returnValues=new ArrayList();
for(int i=oldTop+1;i<=newTop;i++)
{
returnValues.Add(getObject(luaState,i));
}
LuaDLL.lua_settop(luaState,oldTop);
return returnValues.ToArray();
}
}
/*
* Gets the values from the provided index to
* the top of the stack and returns them in an array, casting
* them to the provided types.
*/
internal object[] popValues(IntPtr luaState,int oldTop,Type[] popTypes)
{
int newTop=LuaDLL.lua_gettop(luaState);
if(oldTop==newTop)
{
return null;
}
else
{
int iTypes;
ArrayList returnValues=new ArrayList();
if(popTypes[0] == typeof(void))
iTypes=1;
else
iTypes=0;
for(int i=oldTop+1;i<=newTop;i++)
{
returnValues.Add(getAsType(luaState,i,popTypes[iTypes]));
iTypes++;
}
LuaDLL.lua_settop(luaState,oldTop);
return returnValues.ToArray();
}
}
// kevinh - the following line doesn't work for remoting proxies - they always return a match for 'is'
// else if(o is ILuaGeneratedType)
static bool IsILua(object o)
{
if(o is ILuaGeneratedType)
{
// Make sure we are _really_ ILuaGenerated
Type typ = o.GetType();
return (typ.GetInterface("ILuaGeneratedType") != null);
}
else
return false;
}
/*
* Pushes the object into the Lua stack according to its type.
*/
internal void push(IntPtr luaState, object o)
{
if(o==null)
{
LuaDLL.lua_pushnil(luaState);
}
else if(o is sbyte || o is byte || o is short || o is ushort ||
o is int || o is uint || o is long || o is float ||
o is ulong || o is decimal || o is double)
{
double d=Convert.ToDouble(o);
LuaDLL.lua_pushnumber(luaState,d);
}
else if(o is char)
{
double d = (char)o;
LuaDLL.lua_pushnumber(luaState,d);
}
else if(o is string)
{
string str=(string)o;
LuaDLL.lua_pushstring(luaState,str);
}
else if(o is bool)
{
bool b=(bool)o;
LuaDLL.lua_pushboolean(luaState,b);
}
else if(IsILua(o))
{
(((ILuaGeneratedType)o).__luaInterface_getLuaTable()).push(luaState);
}
else if(o is LuaTable)
{
((LuaTable)o).push(luaState);
}
else if(o is LuaCSFunction)
{
pushFunction(luaState,(LuaCSFunction)o);
}
else if(o is LuaFunction)
{
((LuaFunction)o).push(luaState);
}
else
{
pushObject(luaState,o,"luaNet_metatable");
}
}
/*
* Checks if the method matches the arguments in the Lua stack, getting
* the arguments if it does.
*/
internal bool matchParameters(IntPtr luaState,MethodBase method,ref MethodCache methodCache)
{
return metaFunctions.matchParameters(luaState,method,ref methodCache);
}
internal Array TableToArray(Func<int, object> luaParamValue, Type paramArrayType, int startIndex, int count) {
return metaFunctions.TableToArray(luaParamValue,paramArrayType, startIndex, count);
}
}
}