/* * Gets the table in the index positon of the Lua stack. */ internal LuaTable getTable(LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue(luaState, index); return(new LuaTable(LuaLib.lua_ref(luaState, 1), interpreter)); }
/// <summary> /// Pops a value from the lua stack. /// </summary> /// <returns>Returns the top value from the lua stack.</returns> public object Pop() { int top = LuaLib.LuaGetTop(luaState); return(translator.PopValues(luaState, top - 1) [0]); }
/// <summary> /// Tries to set a named property or field /// </summary> /// <param name="luaState"></param> /// <param name="targetType"></param> /// <param name="target"></param> /// <param name="bindingType"></param> /// <returns>false if unable to find the named member, true for success</returns> private bool TrySetMember(LuaState luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage) { detailMessage = null; // No error yet // If not already a string just return - we don't want to call tostring - which has the side effect of // changing the lua typecode to string // Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to // be true for isstring. if (LuaLib.LuaType(luaState, 2) != LuaTypes.String) { detailMessage = "property names must be strings"; return(false); } // We only look up property names by string string fieldName = LuaLib.LuaToString(luaState, 2).ToString(); if (fieldName == null || fieldName.Length < 1 || !(char.IsLetter(fieldName [0]) || fieldName [0] == '_')) { detailMessage = "invalid property name"; return(false); } // Find our member via reflection or the cache var member = (MemberInfo)CheckMemberCache(memberCache, targetType, fieldName); if (member == null) { //CP: Removed NonPublic binding search and made case insensitive var members = targetType.GetMember(fieldName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/); if (members.Length > 0) { member = members [0]; SetMemberCache(memberCache, targetType, fieldName, member); } else { detailMessage = "field or property '" + fieldName + "' does not exist"; return(false); } } if (member.MemberType == MemberTypes.Field) { var field = (FieldInfo)member; object val = translator.GetAsType(luaState, 3, field.FieldType); try { field.SetValue(target, val); } catch (Exception e) { ThrowError(luaState, e); } // We did a call return(true); } else if (member.MemberType == MemberTypes.Property) { var property = (PropertyInfo)member; object val = translator.GetAsType(luaState, 3, property.PropertyType); try { property.SetValue(target, val, null); } catch (Exception e) { ThrowError(luaState, e); } // We did a call return(true); } detailMessage = "'" + fieldName + "' is not a .net field or property"; return(false); }
private int getMethodInternal(LuaCore.lua_State luaState) { object obj = translator.getRawNetObject(luaState, 1); if (obj.IsNull()) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaLib.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); //var indexType = index.GetType(); string methodName = index as string; // will be null if not a string arg var 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.IsNull() && isMemberPresent(objType, methodName)) { return(getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } } catch { } // 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); if (objType.UnderlyingSystemType == typeof(float[])) { float[] arr = ((float[])obj); translator.push(luaState, arr [intIndex]); } else if (objType.UnderlyingSystemType == typeof(double[])) { double[] arr = ((double[])obj); translator.push(luaState, arr [intIndex]); } else if (objType.UnderlyingSystemType == typeof(int[])) { int[] arr = ((int[])obj); translator.push(luaState, arr [intIndex]); } else { object[] arr = (object[])obj; translator.push(luaState, arr [intIndex]); } } else { // Try to use get_Item to index into this .net object var methods = objType.GetMethods(); foreach (var mInfo in methods) { if (mInfo.Name == "get_Item") { //check if the signature matches the input if (mInfo.GetParameters().Length == 1) { var getter = mInfo; var actualParms = (!getter.IsNull()) ? getter.GetParameters() : null; if (actualParms.IsNull() || actualParms.Length != 1) { translator.throwError(luaState, "method not found (or no indexer): " + index); LuaLib.lua_pushnil(luaState); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms [0].ParameterType); object[] args = new object[1]; // Just call the indexer - if out of bounds an exception will happen args [0] = index; try { object result = getter.Invoke(obj, args); translator.push(luaState, result); } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { translator.throwError(luaState, "key '" + index + "' not found "); } else { translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message); } LuaLib.lua_pushnil(luaState); } } } } } } LuaLib.lua_pushboolean(luaState, false); return(2); }
private object getAsBoolean(LuaCore.lua_State luaState, int stackPos) { return(LuaLib.lua_toboolean(luaState, stackPos)); }
/* * Matches a method against its arguments in the Lua stack. Returns * if the match was succesful. It it was also returns the information * necessary to invoke the method. */ internal bool MatchParameters(LuaState luaState, MethodBase method, ref MethodCache methodCache) { ExtractValue extractValue; bool isMethod = true; var paramInfo = method.GetParameters(); int currentLuaParam = 1; int nLuaParams = LuaLib.LuaGetTop(luaState); var paramList = new List <object> (); var outList = new List <int> (); var argTypes = new List <MethodArgs> (); foreach (var currentNetParam in paramInfo) { #if !SILVERLIGHT if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params #else if (currentNetParam.IsOut) // Skips out params #endif { paramList.Add(null); outList.Add(paramList.LastIndexOf(null)); } else if (IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking { var value = extractValue(luaState, currentLuaParam); paramList.Add(value); int index = paramList.LastIndexOf(value); var methodArg = new MethodArgs(); methodArg.index = index; methodArg.extractValue = extractValue; argTypes.Add(methodArg); if (currentNetParam.ParameterType.IsByRef) { outList.Add(index); } currentLuaParam++; } // Type does not match, ignore if the parameter is optional else if (IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue)) { var paramArrayType = currentNetParam.ParameterType.GetElementType(); Func <int, object> extractDelegate = (currentParam) => { currentLuaParam++; return(extractValue(luaState, currentParam)); }; int count = (nLuaParams - currentLuaParam) + 1; Array paramArray = TableToArray(extractDelegate, paramArrayType, currentLuaParam, count); paramList.Add(paramArray); int index = paramList.LastIndexOf(paramArray); var methodArg = new MethodArgs(); methodArg.index = index; methodArg.extractValue = extractValue; methodArg.isParamsArray = true; methodArg.paramsArrayType = paramArrayType; argTypes.Add(methodArg); } else if (currentLuaParam > nLuaParams) // Adds optional parameters { if (currentNetParam.IsOptional) { paramList.Add(currentNetParam.DefaultValue); } else { isMethod = false; break; } } else if (currentNetParam.IsOptional) { paramList.Add(currentNetParam.DefaultValue); } else // No match { isMethod = false; break; } } if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match { isMethod = false; } if (isMethod) { methodCache.args = paramList.ToArray(); methodCache.cachedMethod = method; methodCache.outList = outList.ToArray(); methodCache.argTypes = argTypes.ToArray(); } return(isMethod); }
/* * Gets the table in the index positon of the Lua stack. */ internal LuaTable GetTable(LuaState luaState, int index) { LuaLib.LuaPushValue(luaState, index); return(new LuaTable(LuaLib.LuaRef(luaState, 1), interpreter)); }
internal ExtractValue CheckLuaType(LuaState luaState, int stackPos, Type paramType) { var luatype = LuaLib.LuaType(luaState, stackPos); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } var underlyingType = Nullable.GetUnderlyingType(paramType); if (underlyingType != null) { paramType = underlyingType; // Silently convert nullable types to their non null requics } var extractKey = GetExtractDictionaryKey(paramType); if (paramType.Equals(typeof(object))) { return(extractValues [extractKey]); } //CP: Added support for generic parameters if (paramType.IsGenericParameter) { if (luatype == LuaTypes.Boolean) { return(extractValues [GetExtractDictionaryKey(typeof(bool))]); } else if (luatype == LuaTypes.String) { return(extractValues[GetExtractDictionaryKey(typeof(string))]); } else if (luatype == LuaTypes.Table) { return(extractValues [GetExtractDictionaryKey(typeof(LuaTable))]); } else if (luatype == LuaTypes.UserData) { return(extractValues [GetExtractDictionaryKey(typeof(object))]); } else if (luatype == LuaTypes.Function) { return(extractValues [GetExtractDictionaryKey(typeof(LuaFunction))]); } else if (luatype == LuaTypes.Number) { return(extractValues [GetExtractDictionaryKey(typeof(double))]); } } if (LuaLib.LuaIsNumber(luaState, stackPos)) { return(extractValues [extractKey]); } if (paramType == typeof(bool)) { if (LuaLib.LuaIsBoolean(luaState, stackPos)) { return(extractValues [extractKey]); } } else if (paramType == typeof(string) || paramType == typeof(char [])) { if (LuaLib.LuaIsString(luaState, stackPos)) { return(extractValues [extractKey]); } else if (luatype == LuaTypes.Nil) { return(extractNetObject); // kevinh - silently convert nil to a null string pointer } } else if (paramType == typeof(LuaTable)) { if (luatype == LuaTypes.Table) { return(extractValues [extractKey]); } } else if (paramType == typeof(LuaUserData)) { if (luatype == LuaTypes.UserData) { return(extractValues [extractKey]); } } else if (paramType == typeof(LuaFunction)) { if (luatype == LuaTypes.Function) { return(extractValues [extractKey]); } } else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.Function) { return(new ExtractValue(new DelegateGenerator(translator, paramType).ExtractGenerated)); } else if (paramType.IsInterface && luatype == LuaTypes.Table) { return(new ExtractValue(new ClassGenerator(translator, paramType).ExtractGenerated)); } else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.Nil) { // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return(extractNetObject); } else if (LuaLib.LuaType(luaState, stackPos) == LuaTypes.Table) { if (LuaLib.LuaLGetMetafield(luaState, stackPos, "__index")) { object obj = translator.GetNetObject(luaState, -1); LuaLib.LuaSetTop(luaState, -2); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } else { return(null); } } else { object obj = translator.GetNetObject(luaState, stackPos); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } return(null); }
/* * Gets the CLR object in the index position of the Lua stack. Returns * delegates as is. */ internal object getRawNetObject(LuaCore.lua_State luaState, int index) { int udata = LuaLib.luanet_rawnetobj(luaState, index); return(udata != -1 ? objects [udata] : null); }
/* * Pushes this table into the Lua stack */ internal void Push(LuaState luaState) { LuaLib.LuaGetRef(luaState, _Reference); }
/* * Gets the CLR object in the index positon of the Lua stack. Returns * delegates as Lua functions. */ internal object getNetObject(LuaCore.lua_State luaState, int index) { int idx = LuaLib.luanet_tonetobject(luaState, index); return(idx != -1 ? objects [idx] : null); }
/* * Gets the function in the index positon of the Lua stack. */ internal LuaFunction getFunction(LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue(luaState, index); return(new LuaFunction(LuaLib.lua_ref(luaState, 1), interpreter)); }
/* * Gets the userdata in the index positon of the Lua stack. */ internal LuaUserData getUserData(LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue(luaState, index); return(new LuaUserData(LuaLib.lua_ref(luaState, 1), interpreter)); }
// #endif static int PanicCallback(LuaState luaState) { string reason = string.Format("unprotected error in call to Lua API ({0})", LuaLib.LuaToString(luaState, -1)); throw new LuaException(reason); }
/* * Gets the userdata in the index positon of the Lua stack. */ internal LuaUserData GetUserData(LuaState luaState, int index) { LuaLib.LuaPushValue(luaState, index); return(new LuaUserData(LuaLib.LuaRef(luaState, 1), interpreter)); }
public void LoadCLRPackage() { LuaLib.LuaLDoString(luaState, Lua.clr_package); }
/* * Gets the function in the index positon of the Lua stack. */ internal LuaFunction GetFunction(LuaState luaState, int index) { LuaLib.LuaPushValue(luaState, index); return(new LuaFunction(LuaLib.LuaRef(luaState, 1), interpreter)); }
private object GetAsBoolean(LuaState luaState, int stackPos) { return(LuaLib.LuaToBoolean(luaState, stackPos)); }
static int PushError(LuaState luaState, string msg) { LuaLib.LuaPushNil(luaState); LuaLib.LuaPushString(luaState, msg); return(2); }
internal ExtractValue checkType(LuaCore.lua_State luaState, int stackPos, Type paramType) { var luatype = LuaLib.lua_type(luaState, stackPos); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } var underlyingType = Nullable.GetUnderlyingType(paramType); if (!underlyingType.IsNull()) { 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.Boolean) { return(extractValues [typeof(bool).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.String) { return(extractValues [typeof(string).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.Table) { return(extractValues [typeof(LuaTable).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.UserData) { return(extractValues [typeof(object).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.Function) { return(extractValues [typeof(LuaFunction).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.Number) { return(extractValues [typeof(double).TypeHandle.Value.ToInt64()]); } } if (LuaLib.lua_isnumber(luaState, stackPos)) { return(extractValues [runtimeHandleValue]); } if (paramType == typeof(bool)) { if (LuaLib.lua_isboolean(luaState, stackPos)) { return(extractValues [runtimeHandleValue]); } } else if (paramType == typeof(string)) { if (LuaLib.lua_isstring(luaState, stackPos)) { return(extractValues [runtimeHandleValue]); } else if (luatype == LuaTypes.Nil) { return(extractNetObject); // kevinh - silently convert nil to a null string pointer } } else if (paramType == typeof(LuaTable)) { if (luatype == LuaTypes.Table) { return(extractValues [runtimeHandleValue]); } } else if (paramType == typeof(LuaUserData)) { if (luatype == LuaTypes.UserData) { return(extractValues [runtimeHandleValue]); } } else if (paramType == typeof(LuaFunction)) { if (luatype == LuaTypes.Function) { return(extractValues [runtimeHandleValue]); } } else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.Function) { return(new ExtractValue(new DelegateGenerator(translator, paramType).extractGenerated)); } else if (paramType.IsInterface && luatype == LuaTypes.Table) { return(new ExtractValue(new ClassGenerator(translator, paramType).extractGenerated)); } else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.Nil) { // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return(extractNetObject); } else if (LuaLib.lua_type(luaState, stackPos) == LuaTypes.Table) { if (LuaLib.luaL_getmetafield(luaState, stackPos, "__index")) { object obj = translator.getNetObject(luaState, -1); LuaLib.lua_settop(luaState, -2); if (!obj.IsNull() && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } else { return(null); } } else { object obj = translator.getNetObject(luaState, stackPos); if (!obj.IsNull() && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } return(null); }
/* * Registers the indexing function of CLR objects * passed to Lua */ private void CreateIndexingMetaFunction(LuaState luaState) { LuaLib.LuaPushString(luaState, "luaNet_indexfunction"); LuaLib.LuaLDoString(luaState, MetaFunctions.LuaIndexFunction); LuaLib.LuaRawSet(luaState, (int)LuaIndexes.Registry); }
private int SetFieldOrPropertyInternal(LuaState luaState) { object target = translator.GetRawNetObject(luaState, 1); if (target == null) { translator.ThrowError(luaState, "trying to index and invalid object reference"); return(0); } var type = target.GetType(); // First try to look up the parameter as a property name string detailMessage; bool didMember = 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 && LuaLib.LuaIsNumber(luaState, 2)) { int index = (int)LuaLib.LuaToNumber(luaState, 2); var 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 var setter = type.GetMethod("set_Item"); if (setter != null) { var args = setter.GetParameters(); var valueType = args [1].ParameterType; // The new val ue the user specified object val = translator.GetAsType(luaState, 3, valueType); var 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 } } #if !SILVERLIGHT } catch (SEHException) { // If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it throw; #endif } catch (Exception e) { ThrowError(luaState, e); } return(0); }
/* * Gets the CLR object in the index positon of the Lua stack. Returns * delegates as Lua functions. */ internal object GetNetObject(LuaState luaState, int index) { int idx = LuaLib.LuaNetToNetObject(luaState, index); return(idx != -1 ? objects [idx] : null); }
private static int runFunctionDelegate(LuaCore.lua_State luaState, ObjectTranslator translator) { LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject(luaState, 1); LuaLib.lua_remove(luaState, 1); return(func(luaState)); }
/* * Gets the CLR object in the index position of the Lua stack. Returns * delegates as is. */ internal object GetRawNetObject(LuaState luaState, int index) { int udata = LuaLib.LuaNetRawNetObj(luaState, index); return(udata != -1 ? objects [udata] : null); }
/* * Pushes the value of a member or a delegate to call it, depending on the type of * the member. Works with static or instance members. * Uses reflection to find members, and stores the reflected MemberInfo object in * a cache (indexed by the type of the object and the name of the member). */ private int getMember(LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType) { bool implicitStatic = false; MemberInfo member = null; object cachedMember = checkMemberCache(memberCache, objType, methodName); //object cachedMember=null; if (cachedMember is LuaCore.lua_CFunction) { translator.pushFunction(luaState, (LuaCore.lua_CFunction)cachedMember); translator.push(luaState, true); return(2); } else if (!cachedMember.IsNull()) { member = (MemberInfo)cachedMember; } else { //CP: Removed NonPublic binding search var members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/); if (members.Length > 0) { member = members [0]; } else { // If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static // lookups for fields/properties/events -kevinh //CP: Removed NonPublic binding search and made case insensitive members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/); if (members.Length > 0) { member = members [0]; implicitStatic = true; } } } if (!member.IsNull()) { if (member.MemberType == MemberTypes.Field) { var field = (FieldInfo)member; if (cachedMember.IsNull()) { setMemberCache(memberCache, objType, methodName, member); } try { translator.push(luaState, field.GetValue(obj)); } catch { LuaLib.lua_pushnil(luaState); } } else if (member.MemberType == MemberTypes.Property) { var property = (PropertyInfo)member; if (cachedMember.IsNull()) { setMemberCache(memberCache, objType, methodName, member); } try { object val = property.GetValue(obj, null); translator.push(luaState, val); } catch (ArgumentException) { // If we can't find the getter in our class, recurse up to the base class and see // if they can help. if (objType is Type && !(((Type)objType) == typeof(object))) { return(getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType)); } else { LuaLib.lua_pushnil(luaState); } } catch (TargetInvocationException e) { // Convert this exception into a Lua error ThrowError(luaState, e); LuaLib.lua_pushnil(luaState); } } else if (member.MemberType == MemberTypes.Event) { var eventInfo = (EventInfo)member; if (cachedMember.IsNull()) { setMemberCache(memberCache, objType, methodName, member); } translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo)); } else if (!implicitStatic) { if (member.MemberType == MemberTypes.NestedType) { // kevinh - added support for finding nested types // cache us if (cachedMember.IsNull()) { setMemberCache(memberCache, objType, methodName, member); } // Find the name of our class string name = member.Name; var dectype = member.DeclaringType; // Build a new long name and try to find the type by name string longname = dectype.FullName + "+" + name; var nestedType = translator.FindType(longname); translator.pushType(luaState, nestedType); } else { // Member type must be 'method' var wrapper = new LuaCore.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).invokeFunction); if (cachedMember.IsNull()) { setMemberCache(memberCache, objType, methodName, wrapper); } translator.pushFunction(luaState, wrapper); translator.push(luaState, true); return(2); } } else { // If we reach this point we found a static method, but can't use it in this context because the user passed in an instance translator.throwError(luaState, "can't pass instance to static method " + methodName); LuaLib.lua_pushnil(luaState); } } else { // kevinh - we want to throw an exception because meerly returning 'nil' in this case // is not sufficient. valid data members may return nil and therefore there must be some // way to know the member just doesn't exist. translator.throwError(luaState, "unknown member name " + methodName); LuaLib.lua_pushnil(luaState); } // push false because we are NOT returning a function (see luaIndexFunction) translator.push(luaState, false); return(2); }
/* * Registers the indexing function of CLR objects * passed to Lua */ private void createIndexingMetaFunction(LuaCore.lua_State luaState) { LuaLib.lua_pushstring(luaState, "luaNet_indexfunction"); LuaLib.luaL_dostring(luaState, MetaFunctions.luaIndexFunction); // steffenj: lua_dostring renamed to luaL_dostring LuaLib.lua_rawset(luaState, (int)LuaIndexes.Registry); }