private Type TypeOf(LuaState luaState, int idx) { int udata = LuaLib.LuaNetCheckUData(luaState, 1, "luaNet_class"); if (udata == -1) { return(null); } ProxyType pt = (ProxyType)objects [udata]; return(pt.UnderlyingSystemType); }
private int GetMethodSignatureInternal(LuaState luaState) { ProxyType klass; object target; int udata = luaState.CheckUObject(1, "luaNet_class"); if (udata != -1) { klass = (ProxyType)_objects[udata]; target = null; } else { target = GetRawNetObject(luaState, 1); if (target == null) { ThrowError(luaState, "get_method_bysig: first arg is not type or object reference"); luaState.PushNil(); return(1); } klass = new ProxyType(target.GetType()); } string methodName = luaState.ToString(2, false); var signature = new Type[luaState.GetTop() - 2]; for (int i = 0; i < signature.Length; i++) { signature[i] = FindType(luaState.ToString(i + 3, false)); } try { var method = klass.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, signature); var wrapper = new LuaMethodWrapper(this, target, klass, method); LuaNativeFunction invokeDelegate = wrapper.InvokeFunction; PushFunction(luaState, invokeDelegate); } catch (Exception e) { ThrowError(luaState, e); luaState.PushNil(); } return(1); }
private int GetMethodSignatureInternal(LuaState luaState) { ProxyType klass; object target; int udata = LuaLib.LuaNetCheckUData(luaState, 1, "luaNet_class"); if (udata != -1) { klass = (ProxyType)objects [udata]; target = null; } else { target = GetRawNetObject(luaState, 1); if (target == null) { ThrowError(luaState, "get_method_bysig: first arg is not type or object reference"); LuaLib.LuaPushNil(luaState); return(1); } klass = new ProxyType(target.GetType()); } string methodName = LuaLib.LuaToString(luaState, 2).ToString(); var signature = new Type[LuaLib.LuaGetTop(luaState) - 2]; for (int i = 0; i < signature.Length; i++) { signature [i] = FindType(LuaLib.LuaToString(luaState, i + 3).ToString()); } try { var method = klass.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, signature); PushFunction(luaState, new LuaNativeFunction((new LuaMethodWrapper(this, target, klass, method)).invokeFunction)); } catch (Exception e) { ThrowError(luaState, e); LuaLib.LuaPushNil(luaState); } return(1); }
private int GetConstructorSignatureInternal(LuaState luaState) { ProxyType klass = null; int udata = luaState.CheckUObject(1, "luaNet_class"); if (udata != -1) { klass = (ProxyType)_objects[udata]; } if (klass == null) { ThrowError(luaState, "get_constructor_bysig: first arg is invalid type reference"); } var signature = new Type[luaState.GetTop() - 1]; for (int i = 0; i < signature.Length; i++) { signature[i] = FindType(luaState.ToString(i + 2, false)); } try { ConstructorInfo constructor = klass.UnderlyingSystemType.GetConstructor(signature); var wrapper = new LuaMethodWrapper(this, null, klass, constructor); var invokeDelegate = wrapper.InvokeFunction; PushFunction(luaState, invokeDelegate); } catch (Exception e) { ThrowError(luaState, e); luaState.PushNil(); } return(1); }
/* * Checks if the value at Lua stack index stackPos matches paramType, * returning a conversion function if it does and null otherwise. */ internal ExtractValue GetExtractor (ProxyType paramType) { return GetExtractor (paramType.UnderlyingSystemType); }
/* * Checks if the value at Lua stack index stackPos matches paramType, * returning a conversion function if it does and null otherwise. */ internal ExtractValue GetExtractor(ProxyType paramType) { return(GetExtractor(paramType.UnderlyingSystemType)); }
private int GetMethodSignatureInternal (LuaState luaState) { ProxyType klass; object target; int udata = LuaLib.LuaNetCheckUData (luaState, 1, "luaNet_class"); if (udata != -1) { klass = (ProxyType)objects [udata]; target = null; } else { target = GetRawNetObject (luaState, 1); if (target == null) { ThrowError (luaState, "get_method_bysig: first arg is not type or object reference"); LuaLib.LuaPushNil (luaState); return 1; } klass = new ProxyType(target.GetType ()); } string methodName = LuaLib.LuaToString (luaState, 2).ToString (); var signature = new Type[LuaLib.LuaGetTop (luaState) - 2]; for (int i = 0; i < signature.Length; i++) signature [i] = FindType (LuaLib.LuaToString (luaState, i + 3).ToString ()); try { var method = klass.GetMethod (methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, signature); PushFunction (luaState, new LuaNativeFunction ((new LuaMethodWrapper (this, target, klass, method)).invokeFunction)); } catch (Exception e) { ThrowError (luaState, e); LuaLib.LuaPushNil (luaState); } return 1; }
/// <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> bool TrySetMember (LuaState luaState, ProxyType 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) { var members = targetType.GetMember (fieldName, bindingType | BindingFlags.Public); if (members.Length > 0) { member = members [0]; SetMemberCache (memberCache, targetType, fieldName, member); } else { detailMessage = "field or property '" + fieldName + "' does not exist"; return false; } } #if NETFX_CORE if (member is FieldInfo) { #else if (member.MemberType == MemberTypes.Field) { #endif 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; #if NETFX_CORE } else if (member is PropertyInfo) { #else } else if (member.MemberType == MemberTypes.Property) { #endif 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; } /* * Writes to fields or properties, either static or instance. Throws an error * if the operation is invalid. */ private int SetMember (LuaState luaState, ProxyType targetType, object target, BindingFlags bindingType) { string detail; bool success = TrySetMember (luaState, targetType, target, bindingType, out detail); if (!success) translator.ThrowError (luaState, detail); return 0; } /// <summary> /// Convert a C# exception into a Lua error /// </summary> /// <param name="e"></param> /// We try to look into the exception to give the most meaningful description void ThrowError (LuaState luaState, Exception e) { // If we got inside a reflection show what really happened var te = e as TargetInvocationException; if (te != null) e = te.InnerException; translator.ThrowError (luaState, e); }
public static UnityEngine.Component AddMissComponent(GameObject obj, ProxyType t) { Type _t = t.UnderlyingSystemType; string classname = _t.ToString(); int idx = classname.LastIndexOf("."); classname = classname.Substring(idx + 1, classname.Length - idx - 1); UnityEngine.Component _out = obj.GetComponent(classname); if (null == _out) { _out = obj.AddComponent(_t); } return _out; }
object CheckMemberCache (Dictionary<object, object> memberCache, ProxyType objType, string memberName) { object members = null; if (memberCache.TryGetValue(objType, out members)) { var membersDict = members as Dictionary<object, object>; object memberValue = null; if (members != null && membersDict.TryGetValue(memberName, out memberValue)) { return memberValue; } } return 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). */ int GetMember (LuaState luaState, ProxyType objType, object obj, string methodName, BindingFlags bindingType) { bool implicitStatic = false; MemberInfo member = null; object cachedMember = CheckMemberCache (memberCache, objType, methodName); if (cachedMember is LuaNativeFunction) { translator.PushFunction (luaState, (LuaNativeFunction)cachedMember); translator.Push (luaState, true); return 2; } else if (cachedMember != null) member = (MemberInfo)cachedMember; else { var members = objType.GetMember (methodName, bindingType | BindingFlags.Public); 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 members = objType.GetMember (methodName, bindingType | BindingFlags.Static | BindingFlags.Public); if (members.Length > 0) { member = members [0]; implicitStatic = true; } } } if (member != null) { #if NETFX_CORE if (member is FieldInfo) { #else if (member.MemberType == MemberTypes.Field) { #endif var field = (FieldInfo)member; if (cachedMember == null) SetMemberCache (memberCache, objType, methodName, member); try { var value = field.GetValue (obj); translator.Push (luaState, value); } catch { LuaLib.LuaPushNil (luaState); } #if NETFX_CORE } else if (member is PropertyInfo) { #else } else if (member.MemberType == MemberTypes.Property) { #endif var property = (PropertyInfo)member; if (cachedMember == null) SetMemberCache (memberCache, objType, methodName, member); try { object value = property.GetValue (obj, null); translator.Push (luaState, value); } 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.UnderlyingSystemType != typeof(object)) #if NETFX_CORE return GetMember (luaState, new ProxyType(objType.UnderlyingSystemType.GetTypeInfo().BaseType), obj, methodName, bindingType); #else return GetMember (luaState, new ProxyType(objType.UnderlyingSystemType.BaseType), obj, methodName, bindingType); #endif else LuaLib.LuaPushNil (luaState); } catch (TargetInvocationException e) { // Convert this exception into a Lua error ThrowError (luaState, e); LuaLib.LuaPushNil (luaState); } #if NETFX_CORE } else if (member is EventInfo) { #else } else if (member.MemberType == MemberTypes.Event) { #endif var eventInfo = (EventInfo)member; if (cachedMember == null) SetMemberCache (memberCache, objType, methodName, member); translator.Push (luaState, new RegisterEventHandler (translator.pendingEvents, obj, eventInfo)); } else if (!implicitStatic) { #if NETFX_CORE var typeInfo = member as TypeInfo; if (typeInfo != null && !typeInfo.IsPublic && !typeInfo.IsNotPublic) { #else if (member.MemberType == MemberTypes.NestedType) { #endif // kevinh - added support for finding nested types- // cache us if (cachedMember == null) 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 LuaNativeFunction ((new LuaMethodWrapper (translator, objType, methodName, bindingType)).invokeFunction); if (cachedMember == null) 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.LuaPushNil (luaState); } } else { if (objType.UnderlyingSystemType != typeof(object)) { #if NETFX_CORE return GetMember (luaState, new ProxyType(objType.UnderlyingSystemType.GetTypeInfo().BaseType), obj, methodName, bindingType); #else return GetMember (luaState, new ProxyType(objType.UnderlyingSystemType.BaseType), obj, methodName, bindingType); #endif } // 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.LuaPushNil (luaState); } // push false because we are NOT returning a function (see luaIndexFunction) translator.Push (luaState, false); return 2; }
/// <summary> /// Does this method exist as either an instance or static? /// </summary> /// <param name="objType"></param> /// <param name="methodName"></param> /// <returns></returns> bool IsMemberPresent (ProxyType objType, string methodName) { object cachedMember = CheckMemberCache (memberCache, objType, methodName); if (cachedMember != null) return true; var members = objType.GetMember (methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); return (members.Length > 0); }
private int GetMethodInternal (LuaState luaState) { object obj = translator.GetRawNetObject (luaState, 1); if (obj == null) { translator.ThrowError (luaState, "trying to index an invalid object reference"); LuaLib.LuaPushNil (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 (); var proxyType = new ProxyType (objType); // 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 (!string.IsNullOrEmpty(methodName) && IsMemberPresent (proxyType, methodName)) return GetMember (luaState, proxyType, obj, methodName, BindingFlags.Instance); } 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 NETFX_CORE Type type = objType; #else Type type = objType.UnderlyingSystemType; #endif if (type == typeof(float[])) { float[] arr = ((float[])obj); translator.Push (luaState, arr [intIndex]); } else if (type == typeof(double[])) { double[] arr = ((double[])obj); translator.Push (luaState, arr [intIndex]); } else if (type == typeof(int[])) { int[] arr = ((int[])obj); translator.Push (luaState, arr [intIndex]); } else { object[] arr = (object[])obj; translator.Push (luaState, arr [intIndex]); } } else { if (!string.IsNullOrEmpty (methodName) && IsExtensionMethodPresent (objType, methodName)) { return GetExtensionMethod (luaState, objType, obj, methodName); } // 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 != null) ? getter.GetParameters () : null; if (actualParms == null || actualParms.Length != 1) { translator.ThrowError (luaState, "method not found (or no indexer): " + index); LuaLib.LuaPushNil (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.LuaPushNil (luaState); } } } } } } LuaLib.LuaPushBoolean (luaState, false); return 2; }
/* * Writes to fields or properties, either static or instance. Throws an error * if the operation is invalid. */ private int SetMember (LuaState luaState, ProxyType targetType, object target, BindingFlags bindingType) { string detail; bool success = TrySetMember (luaState, targetType, target, bindingType, out detail); if (!success) translator.ThrowError (luaState, detail); return 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> bool TrySetMember (LuaState luaState, ProxyType 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) { var members = targetType.GetMember (fieldName, bindingType | BindingFlags.Public); 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; }
void SetMemberCache (Dictionary<object, object> memberCache, ProxyType objType, string memberName, object member) { Dictionary<object, object> members = null; object memberCacheValue = null; if (memberCache.TryGetValue(objType, out memberCacheValue)) { members = (Dictionary<object, object>)memberCacheValue; } else { members = new Dictionary<object, object>(); memberCache[objType] = members; } members [memberName] = member; }
// --lua中添加个照相机例子: // local carm=GameObject("carm") // API.AddComponent(carm,Camera) public static UnityEngine.Component AddComponent(GameObject obj, ProxyType t) { return obj.AddComponent(t.UnderlyingSystemType); }