推送一个可执行的函数指针?

通常情况下,只有在数据不属于Lua的标准类型(数字、字符串、布尔等)时,才会推送“userdata”。

但如果要将实际函数指针推送到Lua(不是作为userdata;因为userdata在Lua中不能作为函数执行),假设函数如下:

void nothing(const char* stuff)
{
    do_magic_things_with(stuff);
}

返回值应该像这个本地Lua函数的返回值一样:

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

使用C API可以实现吗?如果可以,如何实现(示例将不胜感激)?

编辑:为了更清楚,值应该由通过C API公开到Lua的函数返回。

原文链接 https://stackoverflow.com/questions/4210644

点赞
stackoverflow用户33252
stackoverflow用户33252

使用lua_pushcfunction

示例在PiL中有提供。

下面是一个遵循当前接受答案形式的示例。

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

/* 这是你想要返回的 C 函数 */
static void
cfunction(const char *s)
{
    puts(s);
}

/* 这是用作 cfunction 的代理函数 */
static int
proxy(lua_State *L)
{
    cfunction(luaL_checkstring(L, 1));
    return 0;
}

/* 这个全局函数将 "cfunction" 返回给 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();

    /* 设置将代理返回给全局函数 */
    lua_pushcfunction(L, getproxy);
    lua_setglobal(L, "getproxy");

    /* 查看是否有效 */
    luaL_dostring(L, "p = getproxy() p('Hello, world!')");

    lua_close(L);

    return 0;
}
2010-11-18 02:34:13
stackoverflow用户1491
stackoverflow用户1491

你可以返回一个带有元表的 userdata,通过 __call 元方法代理你的 C 函数。这样,该 userdata 就可以像一个函数一样被调用。下面是一个完整的程序示例。

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

/* 这是你想要返回的 C 函数 */
static void
cfunction(const char *s)
{
    puts(s);
}

/* 这是将用作 __call 元方法的代理函数 */
static int
proxy(lua_State *L)
{
    luaL_checkudata(L, 1, "proxy");
    cfunction(luaL_checkstring(L, 2));
    return 0;
}

/* 这个全局函数用于返回带有 userdata 代理的 C 函数 */
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();

    /* 创建代理元表 */
    luaL_newmetatable(L, "proxy");
    lua_pushcfunction(L, proxy);
    lua_setfield(L, -2, "__call");

    /* 设置用于返回代理的全局函数 */
    lua_pushcfunction(L, getproxy);
    lua_setglobal(L, "getproxy");

    /* 看看它是否可行 */
    luaL_dostring(L, "p = getproxy() p('Hello, world!')");

    lua_close(L);

    return 0;
}

回想起来,我完全过于深究了你所要求的问题。你实际上只需要创建一个类型为 lua_CFunction 的函数,从 Lua 栈中提取参数并将其传递给目标 C 函数即可。上面的代码逐字回答了你的问题,但是它可能超出了你实际需要完成的范围。

2010-11-18 06:01:37