Lua C API: Handling and storing additional arguments

为君一笑 提交于 2019-12-06 06:43:43

问题


CreateEntity is a C function I bound to Lua in my project. It takes an entity class name string as first argument, and any number of additional arguments which should get passed to the constructor of the chosen entity.

For example, if CreateEntity was a normal Lua function I could do it this way:

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

But how can I do this with a C Lua function?


回答1:


The C function lua_gettop will return how many parameters were passed to your C function. You must either read these all from the stack and store them in a C data structure, or place them in the Lua registry (see Registry and luaL_ref) and store references to them for later use. The example program below uses the registry approach.

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



回答2:


args = {...}
-- (store args somewhere for whatever reason)

The arguments of the call are on the Lua stack and you can do with them as you please: put them in a structure of your own (std::vector<boost::any> or something like that) or store individual arguments in the Lua registry or create a Lua table with the arguments and store that in the registry instead. What suits you better?

TheConstructor( ... )

I'm fairly convinced this part is not possible in C++ the way it is in Lua. C++ requires the number of parameters you pass to a function to be known at compile time.

It's a major inconvenience to try and do those things in C++. Maybe be betters solution will come if you tell us why do you want your CreateEntity function to be on the C++ side instead of Lua.



来源:https://stackoverflow.com/questions/5448654/lua-c-api-handling-and-storing-additional-arguments

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!