Lua_register using const char * actionname, void (* action) ()

I have a lua_State

script ready to go that will call actionname

. You need to register before running the script void(*action)()

. This process is called by a client that doesn't have access to mine lua_State

, and the client doesn't include lua. I cannot change the method signature to lua_CFunction

because the client code will not know the definitions needed to provide this functionality.

I have to provide a function like this:

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);
}

      

How can I wrap an action so that I can insert it into Lua?

+3


source to share


1 answer


One easy way is to give Lua a C closure.

You will need one static function that acts as a dispatcher. When you register a new action, you push the new C closure, setting the user-supplied function as the upvalue for the closure.



When Lua calls it, you will read the upvalue pointer and call that function.

#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;
}

      

+3


source







All Articles