123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- namespace LuaInterface
- {
- using System;
- using System.IO;
- using System.Collections;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Collections.Generic;
- using System.Diagnostics;
-
- /*
- * 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 LuaState interpreter;
- public MetaFunctions metaFunctions;
- public List<Assembly> assemblies;
- private LuaCSFunction registerTableFunction,unregisterTableFunction,getMethodSigFunction,
- getConstructorSigFunction,importTypeFunction,loadAssemblyFunction, ctypeFunction, enumFromIntFunction;
-
- internal EventHandlerContainer pendingEvents = new EventHandlerContainer();
-
- public static ObjectTranslator FromState(IntPtr luaState)
- {
- LuaDLL.lua_getglobal(luaState, "_translator");
- IntPtr thisptr = LuaDLL.lua_touserdata(luaState, -1);
- LuaDLL.lua_pop(luaState, 1);
-
- GCHandle handle = GCHandle.FromIntPtr(thisptr);
- ObjectTranslator translator = (ObjectTranslator)handle.Target;
-
- return translator;
- }
-
- public ObjectTranslator(LuaState interpreter,IntPtr luaState)
- {
- this.interpreter=interpreter;
- typeChecker=new CheckType(this);
- metaFunctions=new MetaFunctions(this);
- assemblies=new List<Assembly>();
- assemblies.Add(Assembly.GetExecutingAssembly());
- importTypeFunction=new LuaCSFunction(importType);
- loadAssemblyFunction=new LuaCSFunction(loadAssembly);
- registerTableFunction=new LuaCSFunction(registerTable);
- unregisterTableFunction=new LuaCSFunction(unregisterTable);
- getMethodSigFunction=new LuaCSFunction(getMethodSignature);
- getConstructorSigFunction=new LuaCSFunction(getConstructorSignature);
-
- ctypeFunction = new LuaCSFunction(ctype);
- enumFromIntFunction = new LuaCSFunction(enumFromInt);
-
- 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);
- //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");
- LuaDLL.lua_pushstdcallcfunction(luaState,ctypeFunction);
- LuaDLL.lua_setglobal(luaState,"ctype");
- LuaDLL.lua_pushstdcallcfunction(luaState,enumFromIntFunction);
- LuaDLL.lua_setglobal(luaState,"enum");
-
- }
-
- /*
- * 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.
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int loadAssembly(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- try
- {
- string assemblyName=LuaDLL.lua_tostring(luaState,1);
-
- Assembly assembly = null;
-
- //assembly = Assembly.GetExecutingAssembly();
-
- try
- {
- assembly = Assembly.Load(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 && !translator.assemblies.Contains(assembly))
- {
- translator.assemblies.Add(assembly);
- }
- }
- catch(Exception e)
- {
- translator.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.
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int importType(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- string className=LuaDLL.lua_tostring(luaState,1);
- Type klass=translator.FindType(className);
- if(klass!=null)
- translator.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.
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int registerTable(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- #if __NOGEN__
- translator.throwError(luaState, "Tables as Objects not implemnented");
- #else
- if(LuaDLL.lua_type(luaState,1)==LuaTypes.LUA_TTABLE)
- {
- LuaTable luaTable=translator.getTable(luaState,1);
- string superclassName = LuaDLL.lua_tostring(luaState, 2);
- if (superclassName != null)
- {
- Type klass = translator.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);
- translator.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 = translator.addObject(obj);
- translator.pushNewObject(luaState, obj, index, "luaNet_searchbase");
- LuaDLL.lua_rawset(luaState, 1);
- }
- else
- translator.throwError(luaState, "register_table: can not find superclass '" + superclassName + "'");
- }
- else
- translator.throwError(luaState, "register_table: superclass name can not be null");
- }
- else translator.throwError(luaState,"register_table: first arg is not a table");
- #endif
- return 0;
- }
- /*
- * Implementation of free_object. Clears the metatable and the
- * base field, freeing the created object for garbage-collection
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int unregisterTable(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- try
- {
- if(LuaDLL.lua_getmetatable(luaState,1)!=0)
- {
- LuaDLL.lua_pushstring(luaState,"__index");
- LuaDLL.lua_gettable(luaState,-2);
- object obj=translator.getRawNetObject(luaState,-1);
- if(obj==null) translator.throwError(luaState,"unregister_table: arg is not valid table");
- FieldInfo luaTableField=obj.GetType().GetField("__luaInterface_luaTable");
- if(luaTableField==null) translator.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 translator.throwError(luaState,"unregister_table: arg is not valid table");
- }
- catch(Exception e)
- {
- translator.throwError(luaState,e.Message);
- }
- return 0;
- }
- /*
- * Implementation of get_method_bysig. Returns nil
- * if no matching method is not found.
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int getMethodSignature(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- IReflect klass; object target;
- int udata=LuaDLL.luanet_checkudata(luaState,1,"luaNet_class");
- if(udata!=-1)
- {
- klass=(IReflect)translator.objects[udata];
- target=null;
- }
- else
- {
- target=translator.getRawNetObject(luaState,1);
- if(target==null)
- {
- translator.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]=translator.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);
- translator.pushFunction(luaState,new LuaCSFunction((new LuaMethodWrapper(translator,target,klass,method)).call));
- }
- catch(Exception e)
- {
- translator.throwError(luaState,e);
- LuaDLL.lua_pushnil(luaState);
- }
- return 1;
- }
- /*
- * Implementation of get_constructor_bysig. Returns nil
- * if no matching constructor is found.
- */
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int getConstructorSignature(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- IReflect klass=null;
- int udata=LuaDLL.luanet_checkudata(luaState,1,"luaNet_class");
- if(udata!=-1)
- {
- klass=(IReflect)translator.objects[udata];
- }
- if(klass==null)
- {
- translator.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]=translator.FindType(LuaDLL.lua_tostring(luaState,i+2));
- try
- {
- ConstructorInfo constructor=klass.UnderlyingSystemType.GetConstructor(signature);
- translator.pushFunction(luaState,new LuaCSFunction((new LuaMethodWrapper(translator,null,klass,constructor)).call));
- }
- catch(Exception e)
- {
- translator.throwError(luaState,e);
- LuaDLL.lua_pushnil(luaState);
- }
- return 1;
- }
-
- private Type typeOf(IntPtr luaState, int idx)
- {
- int udata=LuaDLL.luanet_checkudata(luaState,1,"luaNet_class");
- if (udata == -1) {
- return null;
- } else {
- ProxyType pt = (ProxyType)objects[udata];
- return pt.UnderlyingSystemType;
- }
- }
-
- public int pushError(IntPtr luaState, string msg)
- {
- LuaDLL.lua_pushnil(luaState);
- LuaDLL.lua_pushstring(luaState,msg);
- return 2;
- }
-
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int ctype(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- Type t = translator.typeOf(luaState,1);
- if (t == null) {
- return translator.pushError(luaState,"not a CLR class");
- }
- translator.pushObject(luaState,t,"luaNet_metatable");
- return 1;
- }
-
- [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
- public static int enumFromInt(IntPtr luaState)
- {
- ObjectTranslator translator = ObjectTranslator.FromState(luaState);
- Type t = translator.typeOf(luaState,1);
- if (t == null || ! t.IsEnum) {
- return translator.pushError(luaState,"not an enum");
- }
- object res = null;
- LuaTypes lt = LuaDLL.lua_type(luaState,2);
- if (lt == LuaTypes.LUA_TNUMBER) {
- int ival = (int)LuaDLL.lua_tonumber(luaState,2);
- res = Enum.ToObject(t,ival);
- } else
- if (lt == LuaTypes.LUA_TSTRING) {
- string sflags = LuaDLL.lua_tostring(luaState,2);
- string err = null;
- try {
- res = Enum.Parse(t,sflags);
- } catch (ArgumentException e) {
- err = e.Message;
- }
- if (err != null) {
- return translator.pushError(luaState,err);
- }
- } else {
- return translator.pushError(luaState,"second argument must be a integer or a string");
- }
- translator.pushObject(luaState,res,"luaNet_metatable");
- 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.luaL_ref(luaState,LuaIndexes.LUA_REGISTRYINDEX),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.luaL_ref(luaState,LuaIndexes.LUA_REGISTRYINDEX),interpreter);
- }
- /*
- * Gets the function in the index positon of the Lua stack.
- */
- public LuaFunction getFunction(IntPtr luaState,int index)
- {
- LuaDLL.lua_pushvalue(luaState,index);
- return new LuaFunction(LuaDLL.luaL_ref(luaState,LuaIndexes.LUA_REGISTRYINDEX),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 ! __NOGEN__
- if(o is ILuaGeneratedType)
- {
- // Make sure we are _really_ ILuaGenerated
- Type typ = o.GetType();
-
- return (typ.GetInterface("ILuaGeneratedType") != null);
- }
- else
- #endif
- return false;
- }
-
- /*
- * Pushes the object into the Lua stack according to its type.
- */
- internal void push(IntPtr luaState, object o)
- {
- if((object)o==(object)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))
- {
- #if ! __NOGEN__
- (((ILuaGeneratedType)o).__luaInterface_getLuaTable()).push(luaState);
- #endif
- }
- 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(object luaParamValue, Type paramArrayType) {
- return metaFunctions.TableToArray(luaParamValue,paramArrayType);
- }
- }
- }
|