2010-05-25 13 views
8

Supuse Registrar muchos nombres de funciones diferentes en Lua para la misma función en C. Ahora, cada vez que se llama a mi función C, ¿hay alguna manera de determinar qué nombre de función se invocó?Obtener el comando lua cuando se llama a una función c

por ejemplo:

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

Entonces, ¿cómo puedo obtener el nombre de función de lo que cada vez lo llamó?

+0

¿Por qué quiere que todas las funciones se correspondan con la misma rutina? –

+0

Me gustaría poder llamar a una función que también tiene un puntero, pero dado el sistema actual, solo puedo llamar a funciones estáticas/globales. –

Respuesta

11

Otra forma de atacar su pregunta es usando upvalues. Básicamente, se registra las funciones de C con la función de abajo en lugar de 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); 
} 

Entonces, getFunctionName es sencillo

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

Dicho esto, lo que trata de hacer parecer a pescado - ¿qué estás tratando ¿conseguir? La función runCommand publicada en la pregunta parece una manera horriblemente ineficiente de hacer algo que Lua hace por ti de todos modos.

+0

También puede poner un puntero 'this' en un upvalue/closure. –

+0

¿Qué pasa con el uso de otros parámetros y el número variable de ellos cuando se utilizan valores ascendentes? –

+0

@MariusK: No estoy seguro de lo que quieres decir, ¿puedes dar más detalles? – sbk

0

Desafortunadamente, eso no es posible, entre otras cosas, porque las funciones en Lua en realidad no tienen que tener un nombre en absoluto. (Tenga en cuenta: (loadstring("a=1"))() está ejecutando una función sin nombre regresar de loadstring.)

2

Usted puede utilizar lua_getinfo: http://pgl.yoyo.org/luai/i/lua_getinfo

esto podría funcionar:

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

Hay una advertencia:

nombre: un nombre razonable para la función dada. Debido a que las funciones en Lua son valores de primera clase, no tienen un nombre fijo: algunas funciones pueden ser el valor de múltiples variables globales, mientras que otras pueden almacenarse solo en un campo de tabla. La función lua_getinfo comprueba cómo se llamó a la función para encontrar un nombre adecuado. Si no puede encontrar un nombre, entonces el nombre se establece en NULL.

2

Una solución alternativa sería la de registrar un metatabla de la tabla de entorno Lua que implementa el metamétodo __index para el envío de estas funciones llamadas.

0

Si usted está dispuesto a sorber todas las ejecuciones función desconocida, es posible que pueda jugar con setmetatable y 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") 

En este ejemplo, sólo he sorbió las ejecuciones desconocidos bajo _util en lugar de en la tabla global.

+0

(Lua gurus: por favor siéntase libre de sugerir una mejor sintaxis o cambios de estilo, estaré encantado de incorporarlos. No uso lua con tanta frecuencia, desafortunadamente, a pesar de ser la que lo integró en nuestro motor en el trabajo.) – leander

Cuestiones relacionadas