2010-08-21 5 views
1

Je ne peux pas vraiment faire un court descriptif pour expliquer mon problème, alors désolé pour cela.Lua pile problème

J'appelle une fonction lua appelée hook.Call (event, ...) à partir de C++. Il appelle toutes les fonctions ajoutées avec hook.Add (événement, nom unique, fonction)

Le problème est que lorsque j'appelle la fonction d'impression (...) à l'intérieur d'un crochet, il n'imprime pas ce que vous attendez de lui. print parce que la pile d'appeler un hook est toujours là. Donc, il imprime à partir de cette pile. Et je ne peux pas enlever la pile parce que je ne serais pas capable d'obtenir les valeurs de retour du hook.

L'appel de crochet ressemble à ceci:

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 

} 

Je pensais à imprimer l'image suivante, mais qui sonne vraiment mal et je ne suis même pas sûr que je le ferais.

Les fonctions crochet

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 
} 

La fonction d'impression

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; 
} 

Je n'ai pas plus de cette fonction d'impression. Je l'ai pris du code de mon ami, c'est pourquoi il n'est pas commenté comme ces fonctions de crochet. L'impression fonctionne quand elle n'est pas appelée dans un crochet.

Donc, le problème avec l'impression est qu'elle imprime tout ce qui se trouve dans la pile de hook parce qu'elle est appelée avant de retirer la pile. Je trouve aussi que le push et le popping sont très déroutants, donc ça aide vraiment à commenter le code comme dans les fonctions hook call qui montrent ce qu'est la pile actuellement.

Je suppose que tout le problème est un défaut de conception dans les fonctions de crochet de C++ mais je ne vois vraiment pas comment je le ferais autrement.

+1

Vous avez dit que la fonction d'impression ne répondait pas à vos attentes, mais vous n'avez jamais dit ce que vous attendiez d'elle. On dirait que c'est censé imprimer tout le contenu de la pile, et selon votre question, c'est ce que ça fait. Au fait, il semble qu'il manque un pop à la fin de 'print' (la valeur de' tostring' restera sur la pile). – interjay

+0

Ouais je pensais qu'il y avait quelque chose qui manquait à ma question: Le problème avec l'impression est qu'il imprime tout ce qui est dans la pile de crochet parce qu'il est appelé avant de retirer la pile. Je suis assez nouveau pour C++ et le lua api; Suis-je censé retirer la pile quand j'en ai fini avec quelque chose? J'utilise lua_settop (L, 0) pour l'enlever dans hook :: End() Habituellement, les gens utilisent lua_pop pour enlever une valeur de la pile à la fin. Ne devraient-ils pas tout enlever? Je vais ajouter lua_pop à la fin, mais je ne pense pas que cela résoudra mon problème. – CapsAdmin

+0

Pouvez-vous préciser ce que vous voulez que la fonction print() accomplisse? Comme l'utilisateur l'a souligné, dans sa forme actuelle, il récupère le contenu de la pile. – Adam

Répondre

1

Je suis tombé à la chaîne de la pile au bas de l'impression int comme Interjay mentionné dans un commentaire et il fonctionne comme il devrait maintenant.

Je suis désolé de ne pas être suffisamment descriptif.

+0

Je vous suggère d'accepter votre propre réponse. Sinon, cette question apparaît comme "Sans réponse" sur la liste. – kikito