调用c函数时获取lua命令

时间:2010-05-25 18:02:32

标签: c++ c lua

假设我在Lua中将许多不同的函数名注册到C中的相同函数。现在,每次调用我的C函数时,有没有办法确定调用了哪个函数名?

例如:

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

那么,我如何获得所谓的函数名称呢?

5 个答案:

答案 0 :(得分:11)

攻击您的问题的另一种方法是使用upvalues。基本上,您使用以下函数注册C函数,而不是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);
}

然后,getFunctionName是直接的

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

那就是说,你想做的事似乎很可疑 - 你想要达到什么目的?问题中发布的runCommand函数看起来像是一种非常低效的方式来做Lua为你做的事情。

答案 1 :(得分:2)

您可以使用lua_getinfo:http://pgl.yoyo.org/luai/i/lua_getinfo

这可能有效:

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

有一点需要注意:

  

name:给定函数的合理名称。因为Lua中的函数是一等值,所以它们没有固定的名称:某些函数可能是多个全局变量的值,而其他函数可能只存储在表字段中。 lua_getinfo函数检查函数的调用方式以查找合适的名称。如果找不到名称,则将name设置为NULL。

答案 2 :(得分:2)

另一种解决方案是为Lua环境表注册metatable,该表实现__index元方法以调度这些函数调用。

答案 3 :(得分:0)

不幸的是,这是不可能的 - 除此之外,因为Lua中的函数实际上根本没有名字。 (考虑:(loadstring("a=1"))()正在执行从loadstring返回的无名函数。)

答案 4 :(得分:0)

如果您愿意捏造所有未知函数执行,您可以使用setmetatablecurrying来玩游戏:

    -- 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" )

在这个例子中,我只是在_util下而不是在全局表中添加了未知的执行。