I am loading Lua script with:
lua_State * L = lua_open();
luaL_openlibs(L);
const char lua_script[] = "function sum(a, b) return a+b; end print(\"_lua_\")";
int load_stat = luaL_loadbuffer(L,lua_script,strlen(lua_script),lua_script);
lua_pcall(L, 0, 0, 0);
Now I can call
lua_getglobal(L,"sum");
and get result from it on C-side
However, when I call lua_pcall, script is executed and it leads to output "_lua_" to console. Without lua_pcall, I cannot later access lua_getglobal. Is there any way around this? I dont want to call lua_pcall before setting "entry point" function via lua_getglobal.
If you can modify the script, a different approach to this is to pack your initialization code (the print and whatever else may be there) into a separate function, like so:
lua_State * L = lua_open();
luaL_openlibs(L);
const char lua_script[] = "function sum(a,b) return a+b end return function() print'_lua_' end";
int load_stat = luaL_loadbuffer(L,lua_script,strlen(lua_script),lua_script);
lua_pcall(L, 0, 1, 0); // run the string, defining the function(s)…
// also puts the returned init function onto the stack, which you could just leave
// there, save somewhere else for later use, … then do whatever you need, e.g.
/* begin other stuff */
lua_getglobal(L, "sum");
lua_pushinteger( L, 2 );
lua_pushinteger( L, 3 );
lua_pcall(L, 2, 1, 0);
printf( "2+3=%d\n", lua_tointeger(L,-1) );
lua_pop(L, 1);
/* end other stuff (keep stack balanced!) */
// and then run the init code:
lua_pcall(L, 0, 0, 0); // prints "_lua_"
Now, while you still have to run the chunk to define the function(s), the other initialization code is returned as a function which you can run at a later time / with a modified environment / … (or not at all, if it's unnecessary in your case.)
The function sum is not defined until you run the script because function definition is an assignment in Lua, and it needs to be executed.
So, there is no way to avoid running the script that defines sum. That is what lua_pcall does. You could use lua_call, but then you wouldn't be able to handle errors.
Related
I'm loading a Lua script to be run multiple times and another Lua script that acts as a library that is supposed to be used by the first script.
Let HelloWorldAPI.lua :
function HelloWorld()
return "Hello world"
end
And SomeScript.lua :
HelloWorld()
I'm doing things in the following order :
L = luaL_newstate();
luaL_openlibs( L );
luaL_loadfile( L, "HelloWorldAPI.lua" );
luaL_loadfile( L, "SomeScript.lua" );
...
lua_pcall( L, 0, 0, 0 )
...
lua_pcall( L, 0, 0, 0 )
...
(some pieces of code were removed to keep it simple)
But I'm geting an error saying that I'm trying to call a nil value when calling the HelloWorld function.
Why ?
The function that I declared when the lib script was executed should be global and thus available in SomeScript.lua, right ?
Thank you.
luaL_loadfile(); loads and compiles a chunk, puts it on top of the stack, but does not execute it yet (so, after the first call to luaL_loadfile the function HelloWorld is not yet defined in the global lua state.
Then, you load the file SomeScript.lua, which is now on top of the stack. The call to lua_pcall now executes this chunk at the top, which tries to call the (not yet) defined function HelloWorld, resulting in the error you observe.
With this in mind, that would be the correct order:
luaL_loadfile( L, "HelloWorldAPI.lua" );
lua_pcall( L, 0, 0, 0 );
luaL_loadfile( L, "SomeScript.lua" );
lua_pcall( L, 0, 0, 0 );
However, to load and immediately execute a file you should use luaL_dofile:
luaL_dofile( L, "HelloWorldAPI.lua" );
luaL_dofile( L, "SomeScript.lua" );
luaL_loadfile leaves the compiled script as a function on the stack.
So, the function for SomeScript.lua is at the top, the function for HelloWorldAPI.lua is below it.
What is the best way to deal with nested lua_CFunction calls? Assume I have two function like this:
static int function2(lua_State *L) {
int i = luaL_checkint(L, 1);
/* do something */
return 1;
};
static int function1(lua_State *L) {
struct udata *u = luaL_checkudata(L, 1, UDATA_METATABLE);
int i = luaL_checkint(L, 2);
/* do something */
/* this does not work, first on call stack is udata, not int */
return function2(L);
};
The function call as above does not work. One option is to modify function2() to use the last element (index -1) on stack, but this is not a sollution in general since function2() might be called from various places with different call stacks.
Another way would be to replace the return function2(L); by
lua_pushcfunction(L, function2);
lua_pushvalue(L, 2);
lua_call(L, 1, 1); /* need to know number of results */
I assume this gives function2() its own call stack so there is no need to modify it. But this sollution seems overly complicated for functions with more parameters since it requires duplicating all of them on the stack.
tl;dr: What is the recommended way/a good way to call a lua_CFunction from inside another one?
In function1 you are expecting the bottom of the stack to be user data.
When you call function2 directly, the LuaState has not changed and therefore the bottom is still user data.
You can successfully call function2 from function1 by ensuring an integer is at index 1.
You could do this by calling lua_insert(L, 1) which will move the top (assuming index 2), to index 1.
You could also do this by popping all values the pushing the integer back on:
lua_pop(L, lua_gettop(L));
lua_pushnumber(L, i);
return function2(L);
lua_CFunction is not fully Lua function. It just a way to create Lua function/closure.
static int function1(lua_State *L) {
....
int top = lua_gettop(L);
lua_pushcfunction(L, function2);
lua_pushvalue(L, 2);
lua_call(L, 1, LUA_MULTRET);
return lua_gettop(L) - 1;
}
The Lua equivalent is
function function1(arg)
return (function(arg) --[[body of f2]] end)(arg)
end
So you create each time new function and call it.
For C function it is quite ok because it no need to compile and you do not need upvalue.
Also Lua 5.2 introduce light function for that.
But if you want equivalent for
int i = 1
local function function2(arg)
i = i + 1
...
end
function function1(arg)
return function2(arg)
end
You need a way to find real Lua function e.g. (not tested)
int f2_ref;
static int function1(lua_State *L) {
...
-- push `function2` on stack
lua_rawgeti(L, LUA_REGISTRYINDEX, f2_ref);
-- as above
}
static int function2(lua_State *L) {
int my_upvalue = lua_tonumber(L, lua_upvalueindex(1));
my_upvalue++;
lua_pushnumber(L, my_upvalue);
lua_replace(L, lua_upvalueindex(1));
...
}
int luaopen_foo(lua_State *L){
-- Here we create instance of Lua function(closure)
lua_pushnumber(L, 1);
lua_pushcclosure(L, function2, 1);
f2_ref = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pushcclosure(L, function1, 0);
return 1;
}
I'd say that calling it through lua is the recommended way to do that but if you don't want to do that for some reason then Timma's suggestions are the right ones.
I have the following code:
// global variables
count = 0;
char arr[50][5];
main(){
// do something
}
init(){
count = 0;
memset (arr, 0, sizeof(arr));
}
I need to return 1 if init() is successful, but 0 if not. However, I can't see how init() can technically fail. How should I implement this error handler in init()?
There are 2 issues:
You don't need to return anything if you don't want to, just make the function void
Your init function is not needed as arr is already 0-initialized since it has static storage (global variable).
EDIT
basically main() can modify count and arr, and at some point i need to
re-initialize the global variables using init().
If the function can be called later on it would be useful to call it "reset", "reinit", "clear" etc. "init" makes the reader think it is only called once, at the beginning
According to the write-up i have to return 1 or 0 in init() depending
on whether there's an error...
In that case just say:
/* XXX No other return code is possible. */
return 0;
I'm embedding lua in my C application.
I'm pushing a variable into stack from C side, and want to retrieve it in the lua script itself.
What can I use to get the pushed value in the stack in the script file?
C code:
// ...
result = lua_load(L, luaByteCodeReader, file, "script", "bt");
lua_pushinteger(L, session_id);
if( lua_pcall(L, 1, 0, 0) != 0 )
// ...
In the Script I want to retrieve the session_id value
local session_id = ...
print "Start"
for i = 1, 10 do
print(i, session_id)
end
print "End"
Problem is you're passing parameters to the script loading, depending on your situation you may set a global value instead or call a function.
For instance, say you have a on_init function on your script:
function on_init(session_id)
...do something...
end
You can load the script as you're doing, then get the on_init function on top of the stack and call it with your parameter:
lua_getglobal(L, "on_init");
lua_pushnumber(L, session_id);
/* call the function with 1 arguments, return 0 result */
lua_call(L, 1, 0);
And it's a little bit cleaner.
I want to get several parameters in Lua from a C function.
I tried to push several arguments on the lua stack:
static int myFunc(lua_State *state)
{
lua_pushnumber(state, 1);
lua_pushnumber(state, 2);
lua_pushnumber(state, 3);
return 1;
}
and call it in Lua like this:
local a,b,c = myFunc()
Unfortunately b and c values are nil. I dont want to write a function for every value I need but to take advantage of Luas capabilities to retrieve several arguments from a function.
The return value of the C function is the number of values returned.
Change it to return 3; and you're good to go.
Here, have a reference from Programming in Lua:
static int l_sin (lua_State *L) {
double d = lua_tonumber(L, 1); /* get argument */
lua_pushnumber(L, sin(d)); /* push result */
return 1; /* number of results */
}