Lua C API: обработка и хранение дополнительных аргументов - PullRequest
3 голосов
/ 27 марта 2011

CreateEntity - это функция C, которую я связал с Lua в своем проекте.Он принимает строку имени класса сущности в качестве первого аргумента и любое количество дополнительных аргументов, которые должны быть переданы в конструктор выбранной сущности.

Например, если CreateEntity была нормальной функцией Lua, я мог бы сделать это такСпособ:

function CreateEntity( class, ... )  
    -- (choose a constructor function based on class)
    args = {...}
    -- (store args somewhere for whatever reason)
    TheConstructor( ... )  
end

Но как я могу сделать это с помощью функции C Lua?

Ответы [ 2 ]

4 голосов
/ 28 марта 2011

Функция C lua_gettop вернет, сколько параметров было передано вашей функции C.Вы должны либо прочитать все из стека и сохранить их в структуре данных C, либо поместить их в реестр Lua (см. Registry и luaL_ref ) и сохранить ссылки на них для дальнейшего использованияиспользовать.В приведенном ниже примере программы используется подход реестра.

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>

/* this function prints the name and extra variables as a demonstration */
static void
TheConstructor(lua_State *L, const char *name, int *registry, int n)
{
    int i;

    puts(name);

    for (i = 0; i < n; ++i) {
        lua_rawgeti(L, LUA_REGISTRYINDEX, registry[i]);
        puts(lua_tostring(L, -1));
    }

    free(registry);
}

static int
CreateEntity(lua_State *L)
{
    const char *NAME = luaL_checkstring(L, 1);
    int *registry;
    int i, n;

    /* remove the name parameter from the stack */
    lua_remove(L, 1);

    /* check how many arguments are left */
    n = lua_gettop(L);

    /* create an array of registry entries */
    registry = calloc(n, sizeof (int));
    for (i = n; i > 0; --i)
        registry[i-1] = luaL_ref(L, LUA_REGISTRYINDEX);

    TheContructor(L, NAME, registry, n);

    return 0;
}

int
main(int argc, char **argv[])
{
    const char TEST_CHUNK[] =
        "CreateEntity('foo', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)";
    lua_State *L;

    L = luaL_newstate();
    lua_register(L, "CreateEntity", CreateEntity);
    luaL_dostring(L, TEST_CHUNK);
    lua_close(L);

    return EXIT_SUCCESS;
}
1 голос
/ 27 марта 2011
args = {...}
-- (store args somewhere for whatever reason)

Аргументы вызова находятся в стеке Lua , и вы можете делать с ними, как вам угодно: поместить их в собственную структуру (std::vector<boost::any> или что-то подобное)сохраните отдельные аргументы в реестре Lua или создайте таблицу Lua с аргументами и сохраните ее в реестре.Что вам больше подходит?

TheConstructor( ... )

Я вполне уверен, что эта часть не возможна в C ++, как в Lua.C ++ требует, чтобы количество параметров, передаваемых функции, было известно во время компиляции.

Пытаться делать такие вещи в C ++ - большое неудобство.Может быть, будет лучшее решение, если вы скажете нам, почему вы хотите, чтобы ваша функция CreateEntity была на стороне C ++ вместо Lua.

...