public static void dumpStack(ObjectTranslator translator, IntPtr luaState) { int num = LuaDLL.lua_gettop(luaState); for (int i = 1; i <= num; i++) { LuaTypes type = LuaDLL.lua_type(luaState, i); if (type != LuaTypes.LUA_TTABLE) { LuaDLL.lua_typename(luaState, type); } LuaDLL.lua_tostring(luaState, i); if (type == LuaTypes.LUA_TUSERDATA) { translator.getRawNetObject(luaState, i).ToString(); } } }
/// <summary> /// Debug tool to dump the lua stack /// </summary> /// FIXME, move somewhere else public static void dumpStack(ObjectTranslator translator, IntPtr luaState) { int depth = LuaDLL.lua_gettop(luaState); Debug.WriteLine("lua stack depth: " + depth); for (int i = 1; i <= depth; i++) { LuaTypes type = LuaDLL.lua_type(luaState, i); // we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types string typestr = (type == LuaTypes.LUA_TTABLE) ? "table" : LuaDLL.lua_typename(luaState, type); string strrep = LuaDLL.lua_tostring(luaState, i); if (type == LuaTypes.LUA_TUSERDATA) { object obj = translator.getRawNetObject(luaState, i); strrep = obj.ToString(); } Debug.Print("{0}: ({1}) {2}", i, typestr, strrep); } }
public static int setFieldOrProperty(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); object target = translator.getRawNetObject(luaState, 1); if (target == null) { translator.throwError(luaState, "trying to index and invalid object reference"); return(0); } Type type = target.GetType(); // First try to look up the parameter as a property name string detailMessage; bool didMember = translator.metaFunctions.trySetMember(luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage); if (didMember) { return(0); // Must have found the property name } // We didn't find a property name, now see if we can use a [] style this accessor to set array contents try { if (type.IsArray && LuaDLL.lua_isnumber(luaState, 2)) { int index = (int)LuaDLL.lua_tonumber(luaState, 2); Array arr = (Array)target; object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType()); arr.SetValue(val, index); } else { // Try to see if we have a this[] accessor MethodInfo setter = type.GetMethod("set_Item"); if (setter != null) { ParameterInfo[] args = setter.GetParameters(); Type valueType = args[1].ParameterType; // The new val ue the user specified object val = translator.getAsType(luaState, 3, valueType); Type indexType = args[0].ParameterType; object index = translator.getAsType(luaState, 2, indexType); object[] methodArgs = new object[2]; // Just call the indexer - if out of bounds an exception will happen methodArgs[0] = index; methodArgs[1] = val; setter.Invoke(target, methodArgs); } else { translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best } } } catch (SEHException) { // If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it throw; } catch (Exception e) { translator.metaFunctions.ThrowError(luaState, e); } return(0); }
/* * __call metafunction of CLR delegates, retrieves and calls the delegate. */ private int runFunctionDelegate(LuaCore.lua_State luaState) { LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject(luaState, 1); LuaLib.lua_remove(luaState, 1); return(func(luaState)); }
public static int getMethod(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); object obj = translator.getRawNetObject(luaState, 1); if (obj == null) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); //Type indexType = index.GetType(); //* not used string methodName = index as string; // will be null if not a string arg Type objType = obj.GetType(); // Handle the most common case, looking up the method by name. // CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object, // ie: xmlelement['item'] <- item is a property of xmlelement try { if (methodName != null && translator.metaFunctions.isMemberPresent(objType, methodName)) { return(translator.metaFunctions.getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } } catch { } bool failed = true; // Try to access by array if the type is right and index is an int (lua numbers always come across as double) if (objType.IsArray && index is double) { int intIndex = (int)((double)index); Array aa = obj as Array; if (intIndex >= aa.Length) { return(translator.pushError(luaState, "array index out of bounds: " + intIndex + " " + aa.Length)); } object val = aa.GetValue(intIndex); translator.push(luaState, val); failed = false; } else { // Try to use get_Item to index into this .net object //MethodInfo getter = objType.GetMethod("get_Item"); // issue here is that there may be multiple indexers.. MethodInfo[] methods = objType.GetMethods(); foreach (MethodInfo mInfo in methods) { if (mInfo.Name == "get_Item") { //check if the signature matches the input if (mInfo.GetParameters().Length == 1) { MethodInfo getter = mInfo; ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null; if (actualParms == null || actualParms.Length != 1) { return(translator.pushError(luaState, "method not found (or no indexer): " + index)); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); // Just call the indexer - if out of bounds an exception will happen try { object result = getter.Invoke(obj, new object[] { index }); translator.push(luaState, result); failed = false; } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { return(translator.pushError(luaState, "key '" + index + "' not found ")); } else { return(translator.pushError(luaState, "exception indexing '" + index + "' " + e.Message)); } } } } } } } if (failed) { return(translator.pushError(luaState, "cannot find " + index)); } LuaDLL.lua_pushboolean(luaState, false); return(2); }
/* * __call metafunction of CLR delegates, retrieves and calls the delegate. */ private int runFunctionDelegate(KopiLua.Lua.lua_State luaState) { KopiLua.Lua.lua_CFunction func = (KopiLua.Lua.lua_CFunction)translator.getRawNetObject(luaState, 1); LuaDLL.lua_remove(luaState, 1); return(func(luaState)); }
public static int getMethod(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); object rawNetObject = objectTranslator.getRawNetObject(luaState, 1); if (rawNetObject == null) { objectTranslator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); return(1); } object obj = objectTranslator.getObject(luaState, 2); string text = obj as string; Type type = rawNetObject.GetType(); try { if (text != null && objectTranslator.metaFunctions.isMemberPresent(type, text)) { int result = objectTranslator.metaFunctions.getMember(luaState, type, rawNetObject, text, BindingFlags.IgnoreCase | BindingFlags.Instance); return(result); } } catch { } bool flag = true; if (type.IsArray && obj is double) { int num = (int)((double)obj); Array array = rawNetObject as Array; if (num >= array.Length) { return(objectTranslator.pushError(luaState, string.Concat(new object[] { "array index out of bounds: ", num, " ", array.Length }))); } object value = array.GetValue(num); objectTranslator.push(luaState, value); flag = false; } else { MethodInfo[] methods = type.GetMethods(); MethodInfo[] array2 = methods; for (int i = 0; i < array2.Length; i++) { MethodInfo methodInfo = array2[i]; if (methodInfo.Name == "get_Item" && methodInfo.GetParameters().Length == 1) { MethodInfo methodInfo2 = methodInfo; ParameterInfo[] array3 = (methodInfo2 == null) ? null : methodInfo2.GetParameters(); if (array3 == null || array3.Length != 1) { return(objectTranslator.pushError(luaState, "method not found (or no indexer): " + obj)); } obj = objectTranslator.getAsType(luaState, 2, array3[0].ParameterType); try { object o = methodInfo2.Invoke(rawNetObject, new object[] { obj }); objectTranslator.push(luaState, o); flag = false; } catch (TargetInvocationException ex) { int result; if (ex.InnerException is KeyNotFoundException) { result = objectTranslator.pushError(luaState, "key '" + obj + "' not found "); return(result); } result = objectTranslator.pushError(luaState, string.Concat(new object[] { "exception indexing '", obj, "' ", ex.Message })); return(result); } } } } if (flag) { return(objectTranslator.pushError(luaState, "cannot find " + obj)); } LuaDLL.lua_pushboolean(luaState, false); return(2); }
internal ExtractValue checkType(IntPtr luaState, int stackPos, Type paramType) { LuaTypes luatype = LuaAPI.lua_type(luaState, stackPos); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } Type underlyingType = Nullable.GetUnderlyingType(paramType); if (underlyingType != null) { paramType = underlyingType; // Silently convert nullable types to their non null requics } long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64(); if (paramType.Equals(typeof(object))) { return(extractValues[runtimeHandleValue]); } //CP: Added support for generic parameters if (paramType.IsGenericParameter) { if (luatype == LuaTypes.LUA_TBOOLEAN) { return(extractValues[typeof(bool).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TSTRING) { return(extractValues[typeof(string).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[typeof(LuaTable).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TUSERDATA) { return(extractValues[typeof(object).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[typeof(LuaFunction).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TNUMBER) { return(extractValues[typeof(double).TypeHandle.Value.ToInt64()]); } } if (paramType.IsValueType && luatype == LuaTypes.LUA_TTABLE) { int oldTop = LuaAPI.lua_gettop(luaState); ExtractValue ret = null; LuaAPI.lua_pushvalue(luaState, stackPos); LuaAPI.lua_pushstring(luaState, "class"); LuaAPI.lua_gettable(luaState, -2); if (!LuaAPI.lua_isnil(luaState, -1)) { string cls = LuaAPI.lua_tostring(luaState, -1); if (cls == "Vector3" && paramType == typeof(Vector3)) { ret = extractValues[typeof(Vector3).TypeHandle.Value.ToInt64()]; } else if (cls == "Vector2" && paramType == typeof(Vector2)) { ret = extractValues[typeof(Vector2).TypeHandle.Value.ToInt64()]; } else if (cls == "Quaternion" && paramType == typeof(Quaternion)) { ret = extractValues[typeof(Quaternion).TypeHandle.Value.ToInt64()]; } else if (cls == "Color" && paramType == typeof(Color)) { ret = extractValues[typeof(Color).TypeHandle.Value.ToInt64()]; } else if (cls == "Vector4" && paramType == typeof(Vector4)) { ret = extractValues[typeof(Vector4).TypeHandle.Value.ToInt64()]; } else if (cls == "Ray" && paramType == typeof(Ray)) { ret = extractValues[typeof(Ray).TypeHandle.Value.ToInt64()]; } else { ret = null; } } LuaAPI.lua_settop(luaState, oldTop); if (ret != null) { return(ret); } } if (LuaAPI.lua_isnumber(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } if (paramType == typeof(bool)) { if (LuaAPI.lua_isboolean(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(string)) { if (LuaAPI.lua_isstring(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } else if (luatype == LuaTypes.LUA_TNIL) { return(extractNetObject); // kevinh - silently convert nil to a null string pointer } } else if (paramType == typeof(LuaTable)) { if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(LuaFunction)) { if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[runtimeHandleValue]); } } else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.LUA_TFUNCTION) { translator.throwError(luaState, "Delegates not implemnented"); } else if (paramType.IsInterface && luatype == LuaTypes.LUA_TTABLE) { translator.throwError(luaState, "Interfaces not implemnented"); } else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.LUA_TNIL) { // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return(extractNetObject); } else if (LuaAPI.lua_type(luaState, stackPos) == LuaTypes.LUA_TTABLE) { if (LuaTypes.LUA_TNIL != LuaAPI.luaL_getmetafield(luaState, stackPos, "__index")) { object obj = translator.getNetObject(luaState, -1); LuaAPI.lua_settop(luaState, -2); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } } else { //object obj = translator.getNetObject(luaState, stackPos); //topameng 修改这里使支持注册到c#的lua类 object obj = translator.getRawNetObject(luaState, stackPos); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } return(null); }
internal ExtractValue checkType(IntPtr luaState, int stackPos, Type paramType) { LuaTypes luatype = LuaDLL.lua_type(luaState, stackPos); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } Type underlyingType = Nullable.GetUnderlyingType(paramType); if (underlyingType != null) { paramType = underlyingType; // Silently convert nullable types to their non null requics } long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64(); if (paramType.Equals(typeof(object))) { return(extractValues[runtimeHandleValue]); } //CP: Added support for generic parameters if (paramType.IsGenericParameter) { if (luatype == LuaTypes.LUA_TBOOLEAN) { return(extractValues[typeof(bool).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TSTRING) { return(extractValues[typeof(string).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[typeof(LuaTable).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TUSERDATA) { return(extractValues[typeof(object).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[typeof(LuaFunction).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TNUMBER) { return(extractValues[typeof(double).TypeHandle.Value.ToInt64()]); } //else // suppress CS0642 ; //an unsupported type was encountered } if (LuaDLL.lua_isnumber(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } if (paramType == typeof(bool)) { if (LuaDLL.lua_isboolean(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(string)) { if (LuaDLL.lua_isstring(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } else if (luatype == LuaTypes.LUA_TNIL) { return(extractNetObject); // kevinh - silently convert nil to a null string pointer } } else if (paramType == typeof(LuaTable)) { if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(LuaUserData)) { if (luatype == LuaTypes.LUA_TUSERDATA) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(LuaFunction)) { if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[runtimeHandleValue]); } } else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.LUA_TFUNCTION) { #if __NOGEN__ translator.throwError(luaState, "Delegates not implemnented"); #else return(new ExtractValue(new DelegateGenerator(translator, paramType).extractGenerated)); #endif } else if (paramType.IsInterface && luatype == LuaTypes.LUA_TTABLE) { #if __NOGEN__ translator.throwError(luaState, "Interfaces not implemnented"); #else return(new ExtractValue(new ClassGenerator(translator, paramType).extractGenerated)); #endif } else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.LUA_TNIL) { // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return(extractNetObject); } else if (LuaDLL.lua_type(luaState, stackPos) == LuaTypes.LUA_TTABLE) { if (LuaDLL.luaL_getmetafield(luaState, stackPos, "__index")) { object obj = translator.getNetObject(luaState, -1); LuaDLL.lua_settop(luaState, -2); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } else { return(null); } } else { //object obj = translator.getNetObject(luaState, stackPos); //topameng 修改这里使支持注册到c#的lua类 object obj = translator.getRawNetObject(luaState, stackPos); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } return(null); }