Ejemplo n.º 1
0
        public void PushNewValueObject(IntPtr luaState, object o, int index)
        {
            LuaAPI.luanet_newudata(luaState, index);
            Type t = o.GetType();

            PushMetaTable(luaState, o.GetType());
            if (LuaAPI.lua_isnil(luaState, -1))
            {
                string meta = t.AssemblyQualifiedName;
                Debugger.LogWarning("Create not wrap ulua type:" + meta);
                LuaAPI.lua_settop(luaState, -2);
                LuaAPI.luaL_newmetatable(luaState, meta);
                LuaAPI.lua_pushstring(luaState, "cache");
                LuaAPI.lua_newtable(luaState);
                LuaAPI.lua_rawset(luaState, -3);
                LuaAPI.lua_pushlightuserdata(luaState, LuaAPI.luanet_gettag());
                LuaAPI.lua_pushnumber(luaState, 1);
                LuaAPI.lua_rawset(luaState, -3);
                LuaAPI.lua_pushstring(luaState, "__index");
                LuaAPI.lua_pushstring(luaState, "luaNet_indexfunction");
                LuaAPI.lua_rawget(luaState, LuaAPI.LUA_REGISTRYINDEX);
                LuaAPI.lua_rawset(luaState, -3);
                LuaAPI.lua_pushstring(luaState, "__gc");
                LuaAPI.lua_pushstdcallcfunction(luaState, metaFunctions.gcFunction);
                LuaAPI.lua_rawset(luaState, -3);
                LuaAPI.lua_pushstring(luaState, "__tostring");
                LuaAPI.lua_pushstdcallcfunction(luaState, metaFunctions.toStringFunction);
                LuaAPI.lua_rawset(luaState, -3);
                LuaAPI.lua_pushstring(luaState, "__newindex");
                LuaAPI.lua_pushstdcallcfunction(luaState, metaFunctions.newindexFunction);
                LuaAPI.lua_rawset(luaState, -3);
            }
            LuaAPI.lua_setmetatable(luaState, -2);
        }
Ejemplo n.º 2
0
        static void PushMetaTable(IntPtr L, Type t)
        {
            int reference = -1;

            if (!typeMetaMap.TryGetValue(t, out reference))
            {
                LuaAPI.luaL_getmetatable(L, t.AssemblyQualifiedName);

                if (!LuaAPI.lua_isnil(L, -1))
                {
                    LuaAPI.lua_pushvalue(L, -1);
                    reference = LuaAPI.luaL_ref(L, LuaAPI.LUA_REGISTRYINDEX);
                    typeMetaMap.Add(t, reference);
                }
            }
            else
            {
                LuaAPI.ulua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, reference);
            }
        }
Ejemplo n.º 3
0
        public int call(IntPtr luaState)
        {
            object targetObject;
            bool   failedCall    = true;
            int    nReturnValues = 0;

            if (!LuaAPI.lua_checkstack(luaState, 5))
            {
                throw new LuaException("Lua stack overflow");
            }

            bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static;

            SetPendingException(null);

            if (isStatic)
            {
                targetObject = null;
            }
            else
            {
                targetObject = _ExtractTarget(luaState, 1);
            }

            if (_LastCalledMethod.cachedMethod != null)       // Cached?
            {
                int        numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject
                int        numArgsPassed  = LuaAPI.lua_gettop(luaState) - numStackToSkip;
                MethodBase method         = _LastCalledMethod.cachedMethod;

                if (numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match?
                {
                    if (!LuaAPI.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6))
                    {
                        throw new LuaException("Lua stack overflow");
                    }

                    //这里 args 只是将 _LastCalledMethod.args 拿来做缓冲区用,避免内存再分配, 里面的值是可以干掉的
                    object[] args = _LastCalledMethod.args;

                    try
                    {
                        for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++)
                        {
                            MethodArgs type          = _LastCalledMethod.argTypes[i];
                            object     luaParamValue = type.extractValue(luaState, i + 1 + numStackToSkip);
                            if (_LastCalledMethod.argTypes[i].isParamsArray)
                            {
                                args[type.index] = _Translator.tableToArray(luaParamValue, type.paramsArrayType);
                            }
                            else
                            {
                                args[type.index] = luaParamValue;
                            }

                            if (args[type.index] == null &&
                                !LuaAPI.lua_isnil(luaState, i + 1 + numStackToSkip))
                            {
                                throw new LuaException("argument number " + (i + 1) + " is invalid");
                            }
                        }
                        if ((_BindingType & BindingFlags.Static) == BindingFlags.Static)
                        {
                            _Translator.push(luaState, method.Invoke(null, args));
                        }
                        else
                        {
                            if (_LastCalledMethod.cachedMethod.IsConstructor)
                            {
                                _Translator.push(luaState, ((ConstructorInfo)method).Invoke(args));
                            }
                            else
                            {
                                _Translator.push(luaState, method.Invoke(targetObject, args));
                            }
                        }
                        failedCall = false;
                    }
                    catch (TargetInvocationException e)
                    {
                        return(SetPendingException(e.GetBaseException()));
                    }
                    catch (Exception e)
                    {
                        if (_Members.Length == 1)
                        {
                            return(SetPendingException(e));
                        }
                    }
                }
            }

            // Cache miss
            if (failedCall)
            {
                if (!isStatic)
                {
                    if (targetObject == null)
                    {
                        _Translator.throwError(luaState, String.Format("instance method '{0}' requires a non null target object", _MethodName));
                        LuaAPI.lua_pushnil(luaState);
                        return(1);
                    }
                    LuaAPI.lua_remove(luaState, 1); // Pops the receiver
                }

                bool   hasMatch      = false;
                string candidateName = null;

                foreach (MemberInfo member in _Members)
                {
                    candidateName = member.ReflectedType.Name + "." + member.Name;
                    MethodBase m        = (MethodInfo)member;
                    bool       isMethod = _Translator.matchParameters(luaState, m, ref _LastCalledMethod);
                    if (isMethod)
                    {
                        hasMatch = true;
                        break;
                    }
                }
                if (!hasMatch)
                {
                    string msg = (candidateName == null)
                        ? "invalid arguments to method call"
                        : ("invalid arguments to method: " + candidateName);

                    LuaAPI.luaL_error(luaState, msg);
                    LuaAPI.lua_pushnil(luaState);
                    ClearCachedArgs();
                    return(1);
                }
            }

            if (failedCall)
            {
                if (!LuaAPI.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6))
                {
                    ClearCachedArgs();
                    throw new LuaException("Lua stack overflow");
                }
                try
                {
                    if (isStatic)
                    {
                        _Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
                    }
                    else
                    {
                        if (_LastCalledMethod.cachedMethod.IsConstructor)
                        {
                            _Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
                        }
                        else
                        {
                            _Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args));
                        }
                    }
                }
                catch (TargetInvocationException e)
                {
                    ClearCachedArgs();
                    return(SetPendingException(e.GetBaseException()));
                }
                catch (Exception e)
                {
                    ClearCachedArgs();
                    return(SetPendingException(e));
                }
            }

            // Pushes out and ref return values
            for (int index = 0; index < _LastCalledMethod.outList.Length; index++)
            {
                nReturnValues++;
                _Translator.push(luaState, _LastCalledMethod.args[_LastCalledMethod.outList[index]]);
            }

            //Desc:
            //  if not return void,we need add 1,
            //  or we will lost the function's return value
            //  when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code
            if (!_LastCalledMethod.IsReturnVoid && nReturnValues > 0)
            {
                nReturnValues++;
            }
            ClearCachedArgs();
            return(nReturnValues < 1 ? 1 : nReturnValues);
        }
Ejemplo n.º 4
0
        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);
        }