Reputation: 371
I was wondering the best way to interact with lua I/O in C++ code.
lua script:
while true do
local input = io.read("*line")
if input == "hello" then
print("world")
else
print("hmmm...")
end
end
C++ code:
lua_State* L = luaL_newstate();
luaL_openlibs(L);
int r = luaL_dofile(L, "foo.lua");
When I ran the C++ code, the foo.lua
script I/O seems replacing the original I/O in C++. The another interesting thing is lua's function print
seems to insert the value into the stack.(I can use lua_tostring(L, -1)
to fetch the print message).
What I want to know is there any ways to interact with lua script more elegantly instead of covering my std I/O. Like, if I push the "hello"
into the stack, it can gives me "world" back?
Upvotes: 0
Views: 637
Reputation: 484
This is how I tend to write a C program that executes a Lua script using Lua's C API:
#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#define MIN_ARGC 2
int main(int argc, char** argv) {
// Check to make sure a Lua file was passed to this program as a command-line
// argument.
if (argc < MIN_ARGC) {
fprintf(stderr, "Lua filename expected from command line\n");
exit(EXIT_FAILURE);
}
lua_State* L = luaL_newstate();
// NOTE: good idea to make sure the lua_State* initialized.
if (!L) {
fprintf(stderr, "Error initializing Lua\n");
exit(EXIT_FAILURE);
}
// Open standard Lua libraries--math, string, etc.
luaL_openlibs(L);
// At this point, I register any C functions for use in Lua using the macro
// lua_register.
// I usually create an int called fail; if an error occurs during the execution of
// the Lua script, fail is set to 1.
int fail = 0;
// Execute the Lua script passed to this program as argv[1]; and, in the event of
// an error, print it to stderr.
if ((fail = luaL_dofile(L, argv[1])))
fprintf(stderr, "%s\n", lua_tostring(L, -1));
// Make sure to close your lua_State*.
lua_close(L);
return (fail) ? EXIT_FAILURE : EXIT_SUCCESS;
}
Here is a trivial example of a C function that can be called from Lua. It returns an int
and has one parameter, a lua_State*
:
int lua_foo(lua_State* L) {
printf("foo\n");
return 0;
}
This is a lua_CFunction
, and its return value refers to the number of values it will push on to the Lua stack. In the case of my trivial function lua_foo
, it pushes nothing on to the stack, so it returns 0
.
It could be registered with the macro lua_register
as follows:
lua_register(L, "foo", lua_foo);
It could then be called from Lua, in a script executed by this program via luaL_dofile
, as foo()
.
As for the example script that you provided in your question, there is no condition to break out of the while-loop. Try this instead:
while (true) do
local input = io.read("*l")
if (input == "hello") then
print("world")
-- Include a statement here to break out of the loop once the user has
-- input 'hello'.
break
else
print("hmm...")
end
end
Upon inputting "hello," the loop will break and the script should successfully exit; and the value of r
in your C/C++ code will be set to 0
, indicating normal script execution by luaL_dofile
.
EDIT:
As far as the part of your question concerning Lua I/O and "elegant" interaction with C, you have to remember that Lua is implemented in ANSI C; which means that, at a lower level, Lua calls C functions. There is nothing wrong with calling Lua I/O functions, so long as you handle them correctly, as they are simply Lua wrappers for C functions.
Upvotes: 1