Получите команду lua, когда функция c будет вызвана

Предполагаемый я регистрирую много различных имен функций в 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);
}

Так, как я получаю название того, что когда-нибудь функционирует, назвал его?

8
задан Nick Banks 25 May 2010 в 18:02
поделиться

5 ответов

Другой способ ответить на ваш вопрос - использовать 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 все равно делает за вас.

11
ответ дан 5 December 2019 в 11:22
поделиться

Вы можете использовать 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
ответ дан 5 December 2019 в 11:22
поделиться

Если вы хотите пропустить все выполнение неизвестных функций, вы можете играть в игры с setmetatable и каррированием :

    -- 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 В этом примере я только пропустил неизвестные исполнения в _util , а не в глобальной таблице.

0
ответ дан 5 December 2019 в 11:22
поделиться

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

2
ответ дан 5 December 2019 в 11:22
поделиться

К сожалению, это невозможно - среди прочего, потому что функции в Lua на самом деле вообще не должны иметь имя. (Рассмотрим: (loadstring("a=1"))() выполняет безымянный вызов функции, возвращаемой из loadstring.)

0
ответ дан 5 December 2019 в 11:22
поделиться