Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua get function from argument

Tags:

c++

lua

A simple example of producing.

protocol.onConnect(function() end, function () end, ...)

Now in c, i want to get the functions which are in args #1, #2.
In strings, numbers,... we can get them using (lua_getstring,..), But I at-least didn't found how to get a function.

int luaProtocolOnConnect(lua_State* L)
{
    int base_func // func #1
    int call_func // func #2
    ....
}
like image 414
Slavi Avatar asked Dec 19 '22 15:12

Slavi


2 Answers

You cannot really "get" a Lua function. Lua functions, like Lua tables, are pure-Lua objects. As such, they have no C or C++ analog. If you want to call a Lua function, that's done through lua_call, lua_pcall or similar functions. This is done in-situ on the Lua stack.

So you can't take a Lua function and turn it into a C++ value. What you can do is take a Lua function and manipulate it in the various ways that all Lua objects can be manipulated.

For example, let's say you want to store a Lua function in a C++ object, then later call whatever Lua function was stored there. Well obviously, you can't convert the Lua function directly into a C++ value. What you can do is store that Lua function in a place which C++ can access. You use some value which does have a C++ analog to reference that stored Lua function. The value must be unique for every object you want to store like this. The value you get when storing the object will be saved in your C++ object. When the time comes to retrieve the Lua function, you simply use the stored value to retrieve it.

Because this is an exceedingly common operation, Lua has ways to facilitate this. The first is the Lua registry, a table that C++ can access but Lua code cannot (not unless you give it access).

The second is the luaL_ref series of functions. luaL_ref takes whatever is at the top of the stack and sticks it in a table you provide, returning to you an integer key that can be used to retrieve it later. lua_rawgeti can be used to retrieve the function from the table by the key, and luaL_unref takes the table and the integer key, removing the referenced function from the table when you're done with it.

So if you want to store such functions, you simply need to create such a table, stick it in a known place in the registry (so that you can fetch it whenever you need to), and then use luaL_ref to store those functions. When it comes time to call them, retrieve them with lua_rawgeti. When you're finished using them, destroy them with luaL_unref.

like image 163
Nicol Bolas Avatar answered Dec 24 '22 03:12

Nicol Bolas


You can use lua_isfunction to check if it's a function, use lua_pushvalue to push its value on top of the stack and then use luaL_ref (luaL_ref(L,LUA_REGISTRYINDEX);) to turn it into a unique key you can later reference to retrieve the value (lua_rawgeti(L,LUA_REGISTRYINDEX,ref)) and call the function.

like image 37
Paul Kulchenko Avatar answered Dec 24 '22 02:12

Paul Kulchenko