Calling unknown (by name) lua function from C ++

Here's what I want to do:

1) There is a user-defined lua function that I don't know by name. Let's say that:

function f(x) return 2*x; end

      

2) Then the user will call the function (which was developed in step 3) from Lua, for example:

a=foo(f,3) --expecting a=6

      

3) C ++ function for foo:

int lua_foo(lua_State *L)
{
    int nargs = lua_gettop(L);
    if(nargs<2) throw "ERROR: At least two arguments i) Function ii) number must be supplied";


    int type = lua_type(L, 1);
    if(type!=LUA_TFUNCTION) throw "ERROR: First argument must be a function";

    double arg2=lua_tonumber(L,2);
    lua_pushnumber(L,arg2);

    lua_pcall(L, 1, 1, 0) ; //trying to call the function f

    double result=lua_tonumber(L,-1); //expecting the result to be 6
    lua_pushnumber(L,result);

    lua_pop(L,nargs);

    return 1;
}

      

In C ++ code, I know that the first argument is a function and the second argument is a number. I am trying to call the first argument (function) with the second argument (number) as the argument.

+3


source to share


2 answers


If the function is constructed like this:

/* avoid `lua_` (or `luaL_`) prefix for your own functions */
static int l_foo(lua_State *L)
{
    /* `lauxlib.h` contains a lot of useful helper functions, e.g. for
     * argument type checking: */
    luaL_checktype(L, 1, LUA_TFUNCTION);
    luaL_checknumber(L, 2);
    /* discard any extra arguments to `foo`; ignoring extra arguments
     * is customary for Lua functions */
    lua_settop(L, 2);
    /* the `lua_settop()` above ensures that the two topmost elements
     * of the stack are the function `f` and its argument, so
     * everything is set for the `lua_call()` */
    lua_call(L, 1, 1);
    /* return the topmost value on the Lua stack (the result); all
     * other stack values are removed by Lua automatically (but in
     * this case the result is the only value on the stack as the
     * `lua_call()` popped the function and the argument, and pushed
     * one result) */
    return 1;
}

      



Works as expected.

+3


source


In reading the manuallua_call

, it seems to me that this is a simple stack order problem. The stack must contain, in order, the function to call, followed by the arguments in order.

When you call lua_pcall

, the stack contains a function, an argument, foo

and an argument foo

again that you push. This way the stack foo

was already correct when called and all you have to do is call lua_pcall

without any other push of the stack.




There is also a problem with you popping the result before you push the arguments into foo

from the stack, which will leave the function f

on the stack, not your result. Run the stack first, then push the result.

+2


source







All Articles