What I want to do is create a function that will iterate through some objects and call a function for each function. I'm using BlitzMax, not C, but that is besides the point because it has a full wrapper of Lua's C functions. Lua has a lua_pushcfunction() command, but where's it's lua_pushfunction() command? It is very easy to call functions that have a name, but how do you call a function that was passed as a argument?
Something like:
ForEach( PlanetList, function (planet)
if(planet.exists == true) then
Planet_Count = Planet_Count + 1
end
end )
Usually you just say "lua_getglobal(L,name)" and it puts the lua function nicely on the stack, but how do you get it from an argument?
EDIT
I went back and and actually tried using luaL_ref()
from this question I found earlier. What I am doing is using luaL_ref() to pop the function value from the top of the stack and put it into a temporary register, I used the value returned from luaL_ref()
to use lua_rawgeti()
for each of the items in the list. And then used luaL_unref()
after the list was finished to release that register.
Moreover, for a C function to be called from Lua, we must register it, that is, we must give its address to Lua in an appropriate way. When Lua calls a C function, it uses the same kind of stack that C uses to call Lua. The C function gets its arguments from the stack and pushes the results on the stack.
Many users interact with Lua by using the official interpreter, but even this interpreter is built on top of the C API, without any special access to the language's implementation. In other words, Lua is not only written in C; it is also written to be used from C.
Lua's function , table , userdata and thread (coroutine) types are passed by reference. The other types are passed by value.
The three dots ( ... ) in the parameter list indicate that the function has a variable number of arguments. When this function is called, all its arguments are collected in a single table, which the function accesses as a hidden parameter named arg .
I was having the same question since I'm new to Lua myself. Since, in my opinion, there was no satisfactory answer I figured I would write one, even though this question may not ever be closed. Hopefully this will help some else in this situation.
main.c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
/* this keeps our Lua reference to the Lua function */
int callback_reference = 0;
/* this is called by Lua to register its function */
int lua_registerCallback( lua_State *L ) {
/* store the reference to the Lua function in a variable to be used later */
callback_reference = luaL_ref( L, LUA_REGISTRYINDEX );
return 0;
}
/* calls our Lua callback function and resets the callback reference */
void call_callback( lua_State *L ) {
/* push the callback onto the stack using the Lua reference we */
/* stored in the registry */
lua_rawgeti( L, LUA_REGISTRYINDEX, callback_reference );
/* duplicate the value on the stack */
/* NOTE: This is unnecessary, but it shows how you keep the */
/* callback for later */
lua_pushvalue( L, 1 );
/* call the callback */
/* NOTE: This is using the one we duplicated with lua_pushvalue */
if ( 0 != lua_pcall( L, 0, 0, 0 ) ) {
printf("Failed to call the callback!\n %s\n", lua_tostring( L, -1 ) );
return;
}
/* get a new reference to the Lua function and store it again */
/* NOTE: This is only used in conjunction with the lua_pushvalue */
/* above and can be removed if you remove that */
callback_reference = luaL_ref( L, LUA_REGISTRYINDEX );
}
int main( void ) {
/* set up Lua */
lua_State *L = lua_open();
luaL_openlibs( L );
/* register the lua_registerCallback function as */
/* "RegisterCallback" so it can be called by Lua */
lua_pushcfunction( L, lua_registerCallback );
lua_setglobal( L, "RegisterCallback" );
/* run our Lua file */
if ( 0 != luaL_dofile( L, "callback.lua" ) ) {
printf("Failed to load calback.lua!\n %s",
lua_tostring( L, -1 ) );
lua_close( L );
return 1;
}
/* call the callback */
call_callback( L );
/* call the callback again if you want (because we restored */
/* the Lua function reference) */
call_callback( L );
/* remove the reference to the callback */
/* NOTE: This is also unnecessary if you didn't re-add the */
/* function to the registry */
luaL_unref( L, LUA_REGISTRYINDEX, callback_reference );
/* uninitialize Lua */
lua_close( L );
return 0;
}
callback.lua
function MyCallback()
print("Hello World!")
end
RegisterCallback( MyCallback )
Use lua_pushvalue
once you have the function on the stack to duplicate it.
Update: You will need to call lua_pushvalue() each time you want to call the function as actually calling the function with lua_pcall() or lua_call() will pop the function from the stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With