开发者

Pushing an executable function pointer?

Usually one would only push 'userdata' when the data isn't any of Lua's standard types (number, string, bool, etc).

But how would you push an actually Function pointer to Lua (not as userdata; since userdata is not executable as function in Lua), assuming the function looks like so:

void nothing(const char* stuff)
{
    do_magic_things_with(st开发者_如何学运维uff);
}

The returned value should behave like the returned value from this native Lua function:

function things()
    return function(stuff)
        do_magic_things_with(stuff)
    end
end

Is this possible to do with the C API? If yes, how (Examples would be appreciated)?

EDIT: To add some clarity, The value is supposed to be returned by a function exposed to Lua through the C API.


Use lua_pushcfunction

Examples are included in PiL

Here is an example that follows the form of the currently accepted answer.

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

/* this is the C function you want to return */
static void
cfunction(const char *s)
{
    puts(s);
}

/* this is the proxy function that acts like cfunction */
static int
proxy(lua_State *L)
{
    cfunction(luaL_checkstring(L, 1));
    return 0;
}

/* this global function returns "cfunction" to Lua. */
static int
getproxy(lua_State *L)
{
    lua_pushcfunction(L, &proxy);
    return 1;
}

int
main(int argc, char **argv)
{
    lua_State *L;

    L = luaL_newstate();

    /* set the global function that returns the proxy */
    lua_pushcfunction(L, getproxy);
    lua_setglobal(L, "getproxy");

    /* see if it works */
    luaL_dostring(L, "p = getproxy() p('Hello, world!')");

    lua_close(L);

    return 0;
}


You could return a userdata with a metatable that proxies your C function through the __call metamethod. That way the userdata could be called like a function. Below is a full program example.

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

/* this is the C function you want to return */
static void
cfunction(const char *s)
{
    puts(s);
}

/* this is the proxy function that will be used as the __call metamethod */
static int
proxy(lua_State *L)
{
    luaL_checkudata(L, 1, "proxy");
    cfunction(luaL_checkstring(L, 2));
    return 0;
}

/* this global function returns the C function with a userdata proxy */
static int
getproxy(lua_State *L)
{
    lua_newuserdata(L, sizeof (int));
    luaL_getmetatable(L, "proxy");
    lua_setmetatable(L, -2);
    return 1;
}

int
main(int argc, char **argv)
{
    lua_State *L;

    L = luaL_newstate();

    /* create the proxy metatable */
    luaL_newmetatable(L, "proxy");
    lua_pushcfunction(L, proxy);
    lua_setfield(L, -2, "__call");

    /* set the global function that returns the proxy */
    lua_pushcfunction(L, getproxy);
    lua_setglobal(L, "getproxy");

    /* see if it works */
    luaL_dostring(L, "p = getproxy() p('Hello, world!')");

    lua_close(L);

    return 0;
}

In retrospect, I completely over-thought what you are asking. All you really need to do is to create a function of type lua_CFunction that pulls the parameters from the Lua stack and passes them on to the target C function. The code above answers your question literally, but it is probably overkill for what you really need to accomplish.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜