public object ToCLR(int index = -1) { var type = Type(index); switch (type) { case LuaType.Boolean: return(ToBool(index)); case LuaType.LightUserdata: return(ToLightUserdata(index)); case LuaType.Nil: return(null); case LuaType.None: return(null); case LuaType.Number: return(_ToNumber(index)); case LuaType.String: return(ToString(index)); case LuaType.Userdata: int refidx; try { refidx = _GetCLRReference(index); } catch { return(ToUserdata(index)); } return(Refs.GetRef(refidx)); case LuaType.Function: return("[function]"); case LuaType.Table: return("[table]"); default: throw new LuaException($"Unsupported Lua->CLR conversion for type {type}"); } }
private static int _ConstructorInvoke(IntPtr L) { // upvalues: // 1 - LuaState // 2 - LuaCLRConstructorProxy // 3 - binding_flags (as int) // args: // 1 - type // ... - params var state = Refs.GetRef <LuaState>( _GetCLRReference(L, Lua.lua_upvalueindex(1)) ); var method = Refs.GetRef <LuaCLRConstructorProxy>( _GetCLRReference(L, Lua.lua_upvalueindex(2)) ); var binding_flags = (BindingFlags)(int)Lua.lua_tointeger(L, Lua.lua_upvalueindex(3)); Type type = Refs.GetRef <Type>(_GetCLRReference(L, 1)); var params_offset = 1; var params_len = Lua.lua_gettop(L) - params_offset; var params_ary = new object[params_len]; var params_begin = 1 + params_offset; for (int i = params_begin; i <= params_len + params_offset; i++) { var param = ConvertToCLR(L, i); params_ary[i - (params_begin)] = param; } method.Type = type; object result = null; try { result = method.Invoke(null, binding_flags, params_ary); } catch (Exception e) { state.PushBool(false); //state.Push($"[{e.GetType()}] {e.Message}"); state.PushCLR(e); return(2); } // ErrorMechanism.lua protocol: // return 2 values // 1 - flag (true - success, false - failure) // 2 - error string or return value state.PushBool(true); state.Push(result); return(2); }
private static int _ClrObjectToString(IntPtr L) { // upvalues: // 1 - LuaState // args: // 1 - self var state = Refs.GetRef <LuaState>( _GetCLRReference(L, Lua.lua_upvalueindex(1)) ); var self = Refs.GetRef( _GetCLRReference(L, 1) ); state.PushString(self.ToString()); return(1); }
private static int _LuaCLRFunctionInvoke(IntPtr L) { // upvalues: // 1 - LuaState // 2 - LuaCLRFunction // args: // ... - params var state = Refs.GetRef <LuaState>( _GetCLRReference(L, Lua.lua_upvalueindex(1)) ); var func = Refs.GetRef <LuaCLRFunction>( _GetCLRReference(L, Lua.lua_upvalueindex(2)) ); var params_len = Lua.lua_gettop(L); var params_ary = new object[params_len]; var params_begin = 1; for (int i = params_begin; i <= params_len; i++) { var param = ConvertToCLR(L, i); params_ary[i - (params_begin)] = param; } var top = Lua.lua_gettop(L); int results = 0; try { results = func.Invoke(state); } catch (Exception e) { state.PushBool(false); //state.Push($"[{e.GetType()}] {e.Message}"); state.PushCLR(e); return(2); } // ErrorMechanism.lua protocol: // return 2 values // 1 - flag (true - success, false - failure) // 2 - error string or return value state.PushBool(true); state.Insert(top + 1); return(1 + results); }
internal static object ConvertToCLR(IntPtr L, int index = -1) { var lua_type = Lua.lua_type(L, index); switch (lua_type) { case LuaType.Boolean: return(Lua.lua_toboolean(L, index)); case LuaType.Nil: return(null); case LuaType.Number: var num = Lua.lua_tonumber(L, index); if (num != (long)num) { return(num); } var numlong = Lua.lua_tointeger(L, index); if (numlong > int.MaxValue) { return(numlong); } return((int)Lua.lua_tointeger(L, index)); case LuaType.String: return(ToString(L, index)); case LuaType.Table: return(_TableToCLR(L, index)); case LuaType.LightUserdata: return(Lua.lua_touserdata(L, index)); case LuaType.Userdata: if (IsCLRObject(L, index)) { return(Refs.GetRef(_GetCLRReference(L, index))); } return(Lua.lua_touserdata(L, index)); default: throw new LuaException($"Can't match Lua type {lua_type} to a CLR type"); } }
public static object GetCLRReferenceUpvalue(IntPtr L, int upvalue) { return(Refs.GetRef( _GetCLRReference(L, Lua.lua_upvalueindex(upvalue)) )); }
public static object GetCLRReference(IntPtr L, int index = -1) { return(Refs.GetRef( _GetCLRReference(L, index) )); }
private static int _ClrObjectIndex(IntPtr L) { // upvalues: // 1 - LuaState // 2 - static (true/false) // if true, self is Type // args: // 1 - self // 2 - key var state = Refs.GetRef <LuaState>( _GetCLRReference(L, Lua.lua_upvalueindex(1)) ); var @static = state.ToBool(Lua.lua_upvalueindex(2)); var self = Refs.GetRef(_GetCLRReference(L, 1)); var binding_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type; if (@static) { type = self as Type; self = null; binding_flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; } else { type = self.GetType(); } var key = state.ToString(2); // try field first var field = type.GetField(key, binding_flags); if (field != null) { var value = field.GetValue(self); state.Push(value); return(1); } // then property var prop = type.GetProperty(key, binding_flags); if (prop != null) { var get = prop.GetGetMethod(); if (get != null) { var value = get.Invoke(self, _EmptyObjectArray); state.Push(value); return(1); } else { state.PushNil(); return(1); } } // and now, method if (_TypeHasMethod(type, binding_flags, key)) { // for now we allow access of all methods, including private // need to figure out how to handle that state.PushLuaCLRMethod(type, key, binding_flags); return(1); } // found nothing? return nil state.PushNil(); return(1); }
private static int _ClrObjectNewIndex(IntPtr L) { // upvalues: // 1 - LuaState // 2 - static (true/false) // if true, self is Type // args: // 1 - self // 2 - key // 3 - value var state = Refs.GetRef <LuaState>( _GetCLRReference(L, Lua.lua_upvalueindex(1)) ); var @static = state.ToBool(Lua.lua_upvalueindex(2)); var self = Refs.GetRef(_GetCLRReference(L, 1)); var binding_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type; if (@static) { type = self as Type; self = null; binding_flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; } else { type = self.GetType(); } var key = state.ToString(2); var target_value = state.ToCLR(3); // try field first var field = type.GetField(key, binding_flags); if (field != null) { field.SetValue(self, target_value); return(0); } // then property var prop = type.GetProperty(key, binding_flags); if (prop != null) { var set = prop.GetSetMethod(); if (set != null) { var value = set.Invoke(self, new object[] { target_value }); return(0); } else { state.PushString($"Can't set property '{key}' as it does not have a setter"); return(Lua.lua_error(L)); } } // no methods here // but in the future we could somehow use this for // native patching? // TODO: don't use lua_error state.PushString($"Field/property '{key}' does not exist"); return(Lua.lua_error(L)); }
private object _ToRefObject(int index = -1) { var idx = _GetCLRReference(index); return(Refs.GetRef(idx)); }