Проблема со стеком Lua - PullRequest
       17

Проблема со стеком Lua

1 голос
/ 22 августа 2010

Я не могу сделать короткое, но описательное название, чтобы объяснить мою проблему, так что извините за это.

Я вызываю функцию lua с именем hook.Call (event, ...) из c ++,Он вызывает все функции, добавленные с помощью hook.Add (событие, уникальное_имя, функция)

Проблема в том, что когда я вызываю функцию print (...) внутри ловушки, она не будет печатать то, что вы ожидаетеэто печатать, потому что стек от вызова ловушки все еще там.Так что он печатает из этого стека.И я не могу удалить стек, потому что тогда я не смог бы получить возвращаемые значения из ловушки.

Вызов ловушки выглядит так:

int CGame::Update(bool haveFocus, unsigned int updateFlags)
{

    hook::StartCall("PreGameUpdate");
        hook::PushInteger(haveFocus);
        hook::PushInteger(updateFlags);
    hook::CallReturn(1, 2); //Calls hook.Call("PreGameUpdate", haveFocus, updateFlags) here 

        //The first argument is the amount of values to return to C++
        //The second argument is how many values that were pushed onto the stack (maybe I can monitor that?)

        if(hook::IsBoolean(1) && hook::GetBoolean(1) == false)
            return false; //skip the rest of the code if we return false in the Pre hook

    hook::End();

    //rest of the code in CGame::Update() here

}

Я думалпечати следующего кадра, но это звучит очень плохо, и я даже не уверен, как бы я это сделал.

Функции ловушки

namespace hook
{
    void StartCall(string hookname)
    { lua_State *L = LuaJIT::GetState();

        //Remove any previous stack (just in case?)
        //Stack is now: nil
        lua_settop(L, 0);

        //Get the "hook" global and check if it exists
        //stack is now: hook
        lua_getglobal(L, "hook");
            if (!lua_istable(L, -1))            
                return;

        //Get the function "Call" and check if it exists
        //Stack is now: hook.Call()
        lua_getfield(L, -1, "Call");
            if (!lua_isfunction(L, -1))
                return;

        //Remove the "hook" table from the stack leaving only the Call function left
        //Stack is now: Call()
        lua_remove(L, 1);

        //Push the hookname onto the stack
        //Stack is now: Call(hookname)
        lua_pushstring(L, hookname);
    }

    void CallReturn(int returns, int args)
    { lua_State *L = LuaJIT::GetState();

        //PrintStack("PRE PCALL"); 
        /* When printing the stack, this is the output:
            ===========PRE PCALL=================START

                1: 
            function: 2116D588

                2: 
            PreGameUpdate

                3: 
            1.000000

                4: 
            0.000000

            ===========PRE PCALL=================END
        */

        //Check if the first value is a function and if the stack is valid
        if (!lua_isfunction(L, 1) || lua_gettop(L) == 0)
        {
            PrintStack("NO FUNCTION IN STACK");
            return;
        }

        //pcall "Call" from the stack and check if it worked
        //Stack is now: pcall(Call(hookname, ...))
        int status = lua_pcall(L, args + 1, returns, 0);

        //Check if it errored
        if(status != 0)
        {
            //Print to debug output if it errored
            PrintStack("STACK"); 
            Msg("PCALL ERROR[%s]: %s", lua_tostring(L, 1), lua_tostring(L, -1));
        }
        //PrintStack("POST PCALL"); 
    }

    void End()
    {   lua_State *L = LuaJIT::GetState();

        //Remove the stack again
        //Stack is now: nil
        lua_settop(L, 0);
    }

    void EndNoReturn(int args)
    {
        CallReturn(0, args);
        End();
    }

    void StartCallNoPush(string hookname, int returns)
    {
        StartCall(hookname);
        CallReturn(0, returns);
    }

    void CallSimple(string hookname)
    {
        StartCall(hookname);
        CallReturn(0, 0);
        End();
    }

    void PushBoolean(bool res) 
    { lua_State *L = LuaJIT::GetState();        

        int test = toint(res);

        lua_pushboolean(L, test);
    }
    bool GetBoolean(int idx)
    { lua_State *L = LuaJIT::GetState();    

        int res = lua_toboolean(L, idx);
        lua_pop(L, 1);
        return tobool(res);
    }
    int IsBoolean(int idx)
    { lua_State *L = LuaJIT::GetState();

        int res = lua_isboolean(L, idx);
        lua_pop(L, 1);
        return res;
    }

    //The rest of the code is just like the three functions above but for different types
}

Функция печати

int print(lua_State *L)
{
    //PrintStack("PRINT PRE");
    int n = lua_gettop(L);  /* number of arguments */
    int i;
    lua_getglobal(L, "tostring");
    for (i=1; i<=n; i++) {
        const char *s;
        lua_pushvalue(L, -1);  /* function to be called */
        lua_pushvalue(L, i);   /* value to print */
        lua_call(L, 1, 1);
        s = lua_tostring(L, -1);  /* get result */
        if (s == NULL)
            return luaL_error(L, LUA_QL("tostring") " must return a string to "
                            LUA_QL("print"));
        if (i>1) CryLogAlways("\t");
            CryLogAlways(s);
        lua_pop(L, 1);  /* pop result */
    }
    CryLogAlways("\n");
    //PrintStack("PRINT POST");
    return 0;
}

Я не сделал большую часть этой функции печати.Я взял его из кода моего друга, поэтому он не комментируется так, как эти функции хуков.Печать работает, когда не вызывается в ловушке.

Так что проблема печати в том, что она печатает все, что находится в стеке ловушек, потому что она вызывается до того, как я удаляю стек.нахождение толчков и толчков очень сбивает с толку, так что это действительно помогает комментировать код, такой как в функциях вызова ловушек, показывая, какой стек в данный момент.Я действительно не понимаю, как бы я поступил иначе.

1 Ответ

1 голос
/ 22 августа 2010

Я вытолкнул tostring стека внизу int print, как упоминалось в комментарии между комментариями, и теперь он работает так, как должен.

Прошу прощения, что не достаточно описательный.

...