lua_register 函数中 const char * actionname 和 void(*action)() 参数的使用

我有一个 lua_State 已经准备好了,其中有一个脚本会调用 actionname。 在开始运行脚本之前,需要注册一个 void(*action)(),由一个不具有访问我的 lua_State 的客户端调用此过程,也没有包含 lua。我无法更改方法签名为 lua_CFunction,因为客户端代码不知道提供该函数所需的定义。

我必须提供一个类似于此处的函数:

void registeraction(const char * actionname, void(*action)())
{
    struct functor
    {
        void(*action)();
        functor(void(*action)()) : action(action) {}
        int operator()(lua_State* state) { action(); return 0; }
    };
    functor callme{ action };
    lua_State * L = lua->ptr;
    const char * n = actionname;
    lua_CFunction f{ callme }; //no suitable conversion
    lua_register(L, n, f);
}

如何包装该操作,以便我可以将其推入 Lua 中?

点赞
用户5675002
用户5675002

一种简单的方法是给 Lua 一个 C 闭包。

你需要一个静态函数作为调度程序。注册新的行动时,您会将新的 C 闭包推入栈中,并将用户提供的函数设置为闭包的 upvalue。

当 Lua 调用它时,您将从 upvalue 读取指针并调用该函数。

#include <stdlib.h>
#include <stdio.h>
#include <lua.hpp>

typedef void(*Action)();

// 用户行动
void some_action()
{
    printf("必须行动\n");
}

void other_action()
{
    printf("你好,世界\n");
}

lua_State* L;
static int action_dispatcher(lua_State* L);

// 将此函数暴露给用户
void register_action(const char* name, Action act)
{
    lua_pushlightuserdata(L, (void*)act);
    lua_pushcclosure(L, &action_dispatcher, 1);
    lua_setglobal(L, name);
}

int action_dispatcher(lua_State* L)
{
    Action action = (Action) lua_topointer(L, lua_upvalueindex(1));
    if(action) action();
    return 0;
}

// 测试
int main()
{
    L = luaL_newstate();

    // 注册行动
    register_action("act", &some_action);
    register_action("world", &other_action);

    // “运行”将调用注册行动的脚本
    luaL_dostring(L, "act() world()");
    lua_close(L);
    return EXIT_SUCCESS;
}
2017-05-24 08:26:49