public DynamicLuaTable(LuaTable table, Lua state, string path = null) : base() { this.table = table; this.state = state; if (path == null) { path = LuaHelper.GetRandomString(); //tables need a name, so we can access them } this.path = path; }
private object GetTableValue(string name) { LuaFunction func = GetMetaFunction("index"); if (func != null) //metatable and metamethod set { return(LuaHelper.UnWrapObject(func.Call(table, name)[0], state, path + "." + name)); } else { return(LuaHelper.UnWrapObject(table[name], state, path + "." + name)); } }
/// <summary> /// Wraps an object to prepare it for passing to LuaInterface. If no name is specified, a /// random one with the default length is used. /// </summary> public static object WrapObject(object toWrap, Lua state, string name = null) { if (toWrap is DynamicArray) { //Someone passed an DynamicArray diretly back to Lua. //He wanted to pass the value in the array, so we extract it. //When there is more than one value, this method will ignore these extra value. //This could happen in a situation like this: lua.tmp = lua("return a,b");, but //that doesn't make sense. toWrap = (toWrap as dynamic)[0]; } if (toWrap is MulticastDelegate) { //We have to deal with a problem here: RegisterFunction does not really create //a new function, but a userdata with a __call metamethod. This works fine in all //except two cases: When Lua looks for an __index or __newindex metafunction and finds //a table or userdata, Lua tries to redirect the read/write operation to that table/userdata. //In case of our function that is in reality a userdata this fails. So we have to check //for these function and create a very thin wrapper arround this to make Lua see a function instead //the real userdata. This is no problem for the other metamethods, these are called independent //from their type. (If they are not nil ;)) MulticastDelegate function = (toWrap as MulticastDelegate); if (name != null && (name.EndsWith("__index") || name.EndsWith("__newindex"))) { string tmpName = LuaHelper.GetRandomString(); state.RegisterFunction(tmpName, function.Target, function.Method); state.DoString(String.Format("function {0}(...) return {1}(...) end", name, tmpName), "DynamicLua internal operation"); } else { if (name == null) { name = LuaHelper.GetRandomString(); } state.RegisterFunction(name, function.Target, function.Method); } return(null); } else if (toWrap is DynamicLuaTable) { dynamic dlt = toWrap as DynamicLuaTable; return((LuaTable)dlt); } else { return(toWrap); } }
/// <summary> /// Performs the Power operation on this table. This is only /// needed for languages like C# which have no native operators /// for this. VB etc. users should use the build-in a^b operator. /// </summary> public dynamic Power(object operand) { operand = LuaHelper.WrapObject(operand, state); LuaFunction func = GetMetaFunction("pow"); if (func != null) { return(func.Call(table, operand)); } else { throw new InvalidOperationException("Metamethod __pow not found"); } }
private void SetTableMember(string name, object value) { object tmp = LuaHelper.WrapObject(value, state, path + "." + name); if (tmp != null) //if a function was registered tmp is null, but we dont want to nil the function :P { LuaFunction func = GetMetaFunction("newindex"); if (func != null) { func.Call(table, name, value); } else { table[name] = value; } } }
public override bool TryGetMember(GetMemberBinder binder, out object result) { int index; result = null; if (!int.TryParse(binder.Name, out index)) { return(false); } if (index >= array.Length) { return(false); } result = LuaHelper.UnWrapObject(array[index], state); return(true); }
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { int index; result = null; if (!int.TryParse(indexes[0].ToString(), out index)) { return(false); } if (index >= array.Length) { return(false); } result = LuaHelper.UnWrapObject(array[index], state); return(true); }
private object GetTableValue(string name) { object val = table[name]; if (val != null) { return(LuaHelper.UnWrapObject(val, state, path + "." + name)); } //not found, check __index of metatable LuaFunction func = GetMetaFunction("index"); if (func != null) //metatable and metamethod set { return(LuaHelper.UnWrapObject(func.Call(table, name)[0], state, path + "." + name)); } else { return(null); } }
public dynamic GetMetatable() { return(LuaHelper.UnWrapObject(state.DoString(String.Format("return getmetatable({0})", path), "DynamicLua internal operation")[0], state)); }
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) { string metamethodName; bool switchOperands = false; //Lua has only comparison metamethods for less, so for greater the we have to switch the operands bool negateResult = false; //Lua has only metamethods for equal, so we need this trick here. switch (binder.Operation) { //Math case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: //TODO: Thing about __concat metamethodName = "add"; break; case ExpressionType.Subtract: case ExpressionType.SubtractChecked: case ExpressionType.SubtractAssign: case ExpressionType.SubtractAssignChecked: metamethodName = "sub"; break; case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.MultiplyAssign: case ExpressionType.MultiplyAssignChecked: metamethodName = "mul"; break; case ExpressionType.Divide: case ExpressionType.DivideAssign: metamethodName = "div"; break; case ExpressionType.Modulo: case ExpressionType.ModuloAssign: metamethodName = "mod"; break; case ExpressionType.Power: case ExpressionType.PowerAssign: metamethodName = "pow"; break; //Logic Tests case ExpressionType.Equal: metamethodName = "eq"; break; case ExpressionType.NotEqual: metamethodName = "eq"; negateResult = true; break; case ExpressionType.GreaterThan: metamethodName = "lt"; switchOperands = true; break; case ExpressionType.GreaterThanOrEqual: metamethodName = "le"; switchOperands = true; break; case ExpressionType.LessThan: metamethodName = "lt"; break; case ExpressionType.LessThanOrEqual: metamethodName = "le"; break; default: //This operation is not supported by Lua... result = null; return(false); } LuaFunction mtFunc = GetMetaFunction(metamethodName); if (mtFunc == null) { result = null; return(false); } if (!switchOperands) { result = mtFunc.Call(table, LuaHelper.WrapObject(arg, state))[0]; //Metamethods just return one value, or the other will be ignored anyway } else { result = mtFunc.Call(LuaHelper.WrapObject(arg, state), table)[0]; } if (negateResult && result is bool) //We can't negate if its not bool. If the metamethod returned someting other than bool and ~= is called there will be a bug. (But who would do this?) { result = !(bool)result; } return(true); }
private object GetLuaValue(string name) { return(LuaHelper.UnWrapObject(lua[name], lua, name)); }
static DynamicLua() { LuaHelper.ExtractNativeDlls(); }