lua_register使用const char * actionname,void(* action)()

时间:2017-05-23 17:27:34

标签: c++ lua

我已准备好使用将调用lua_State的脚本actionname。 在脚本启动之前,需要注册void(*action)()。此过程由无法访问我的lua_State的客户端调用,客户端也不包含lua。我无法将方法签名更改为lua_CFunction,因为客户端代码不知道提供该函数的定义needet。

我必须在这里提供类似这样的功能:

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?

1 个答案:

答案 0 :(得分:3)

一种直截了当的方式是给Lua一个C封闭。

您需要一个充当调度程序的静态函数。注册新操作时,推送新的C闭包,将用户提供的函数设置为关闭的up值。

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

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

typedef void(*Action)();

// user actions
void some_action()
{
    printf("Must act\n");
}

void other_action()
{
    printf("Hello world\n");
}

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

// this function will be exposed to users
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;
}

// test it
int main()
{
    L = luaL_newstate();

    // register actions
    register_action("act", &some_action);
    register_action("world", &other_action);

    // "run" script that will call registered actions
    luaL_dostring(L, "act() world()");
    lua_close(L);
    return EXIT_SUCCESS;
}