2010-05-25 8 views
8

supposto mi iscrivo molti nomi di funzioni diverse in Lua per la stessa funzione in C. Ora, ogni volta che la mia funzione C si chiama, c'è un modo per determinare quale funzione nome è stato invocato?Prendi il comando di lua quando una funzione c è chiamata

ad esempio:

int runCommand(lua_State *lua) 
{ 
    const char *name = // getFunctionName(lua) ? how would I do this part 
    for(int i = 0; i < functions.size; i++) 
    if(functions[i].name == name) 
     functions[i].Call() 
} 

int main() 
{ 
    ... 

    lua_register(lua, "delay", runCommand); 
    lua_register(lua, "execute", runCommand); 
    lua_register(lua, "loadPlugin", runCommand); 
    lua_register(lua, "loadModule", runCommand); 
    lua_register(lua, "delay", runCommand); 
} 

Allora, come faccio ad avere il nome di quale funzione sempre ha chiamato?

+0

Perché vuoi tutte le funzioni di mappare per la stessa routine? –

+0

Vorrei poter chiamare una funzione che ha anche un puntatore, ma dato il sistema attuale, posso solo chiamare le funzioni statiche/globali. –

risposta

11

Un altro modo per attaccare la tua domanda è quello di utilizzare upvalues. In sostanza, si registra le funzioni C con la funzione di seguito, invece di lua_register:

void my_lua_register(lua_State *L, const char *name, lua_CFunction f) 
{ 
     lua_pushstring(L, name); 
     lua_pushcclosure(L, f, 1); 
     lua_setglobal(L, name); 
} 

Poi, getFunctionName è dritto in avanti

const char* getFunctionName(lua_State* L) 
{ 
    return lua_tostring(L, lua_upvalueindex(1)); 
} 

Detto questo, ciò che si cerca di fare sembra pesce - cosa stai cercando realizzare? La funzione runCommand pubblicato nella questione si presenta come un modo terribilmente inefficiente di fare qualcosa che Lua fa per voi in ogni caso.

+0

Puoi anche inserire un puntatore 'this' in un valore alto/chiusura. –

+0

Che dire dell'utilizzo di altri parametri e del numero variabile di essi quando si usano valori elevati? –

+0

@ MarisK: Non sono sicuro di cosa intendi, puoi elaborare? – sbk

0

Purtroppo, questo non è possibile - tra le altre cose, perché funzioni in Lua in realtà non devono avere un nome a tutti. (Si pensi: (loadstring("a=1"))() sta eseguendo una funzione senza nome tornato da loadstring.)

2

È possibile utilizzare lua_getinfo: http://pgl.yoyo.org/luai/i/lua_getinfo

questo potrebbe funzionare:

const char* lua_getcurrentfunction(lua_State* L) { 
    lua_Debug ar; 
    lua_getstack(L, 1, &ar); 
    lua_getinfo(L, "f", &ar); 
    return ar.name; 
} 

C'è un avvertimento:

nome: un nome ragionevole per la funzione data. Perché funzioni in Lua sono valori di prima classe, non hanno un nome fisso: alcune funzioni possono essere il valore di molteplici variabili globali, mentre altri possono essere memorizzati solo in un campo di tabella. La funzione lua_getinfo controlla come è stata chiamata la funzione per trovare un nome adatto. Se non riesce a trovare un nome, il nome è impostato su NULL.

2

Una soluzione alternativa sarebbe quella di registrare un metatabella per la tabella ambiente Lua che implementa l'__index metamethod del dispacciamento queste funzioni chiamate.

0

Se siete disposti a trangugiare fino tutte le esecuzioni funzione sconosciuta, si può essere in grado di giocare con setmetatable e currying:

 
    -- This function would not be in lua in your example, 
    -- you'd be doing lua_register(lua, "runCommandNamed", runCommandNamed) 
    -- and writing a runCommandNamed in C. 
    function runCommandNamed(cmd, ...) 
     print("running command", cmd, "with arguments", ...) 
    end 

    -- The rest would be somewhere in lua-land: 
    local utilMetaTable = { 
     __index = function (t, key) 
      return function(...) -- mmm, curry 
       runCommandNamed(key, ...) 
      end 
     end 
    } 

    _util = {} 
    setmetatable(_util, utilMetaTable) 

    -- prints "running command CommandOne  with arguments arg1 arg2 arg3" 
    _util.CommandOne("arg1", "arg2", "arg3") 

    -- prints "running command CommandTwo  with arguments argA argB" 
    _util.CommandTwo("argA", "argB") 

In questo esempio, ho slurped solo fino esecuzioni sconosciuti sotto _util anziché nella tabella globale.

+0

(guru Lua: non esitare a suggerire una migliore sintassi o cambiamenti di stile, sarò lieto di inserirli.) Non uso lua molto spesso, sfortunatamente, nonostante sia quella che l'ha integrata nel nostro motore al lavoro.) – leander

Problemi correlati