Simple Lua Api Example |
|
First, create the below Lua script file and save it as "script.lua". This script will dump to the screen the contents of a table named "foo" (that will be created from the C program) and return the sum of this table's components.
-- script.lua -- Receives a table, returns the sum of its components. io.write("The table the script received has:\n"); x = 0 for i = 1, #foo do print(i, foo[i]) x = x + foo[i] end io.write("Returning data back to C\n"); return x
In order to access it from C, we could hack a little program that would construct the table, pass it to the script, and get the returned value. Create a C program called "test.c" as follows:
/* * test.c * Example of a C program that interfaces with Lua. * Based on Lua 5.0 code by Pedro Martelletto in November, 2003. * Updated to Lua 5.1. David Manura, January 2007. */ #include <lua.h> #include <lualib.h> #include <lauxlib.h> #include <stdlib.h> #include <stdio.h> int main(void) { int status, result, i; double sum; lua_State *L; /* * All Lua contexts are held in this structure. We work with it almost * all the time. */ L = luaL_newstate(); luaL_openlibs(L); /* Load Lua libraries */ /* Load the file containing the script we are going to run */ status = luaL_loadfile(L, "script.lua"); if (status) { /* If something went wrong, error message is at the top of */ /* the stack */ fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1)); exit(1); } /* * Ok, now here we go: We pass data to the lua script on the stack. * That is, we first have to prepare Lua's virtual stack the way we * want the script to receive it, then ask Lua to run it. */ lua_newtable(L); /* We will pass a table */ /* * To put values into the table, we first push the index, then the * value, and then call lua_rawset() with the index of the table in the * stack. Let's see why it's -3: In Lua, the value -1 always refers to * the top of the stack. When you create the table with lua_newtable(), * the table gets pushed into the top of the stack. When you push the * index and then the cell value, the stack looks like: * * <- [stack bottom] -- table, index, value [top] * * So the -1 will refer to the cell value, thus -3 is used to refer to * the table itself. Note that lua_rawset() pops the two last elements * of the stack, so that after it has been called, the table is at the * top of the stack. */ for (i = 1; i <= 5; i++) { lua_pushnumber(L, i); /* Push the table index */ lua_pushnumber(L, i*2); /* Push the cell value */ lua_rawset(L, -3); /* Stores the pair in the table */ } /* By what name is the script going to reference our table? */ lua_setglobal(L, "foo"); /* Ask Lua to run our little script */ result = lua_pcall(L, 0, LUA_MULTRET, 0); if (result) { fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1)); exit(1); } /* Get the returned value at the top of the stack (index -1) */ sum = lua_tonumber(L, -1); printf("Script returned: %.0f\n", sum); lua_pop(L, 1); /* Take the returned value out of the stack */ lua_close(L); /* Cya, Lua */ return 0; }
It's now time to compile it. Keep in mind you'll need to link against -llua (Lua) possibly -lm (the math library). In the system I wrote this simple test, "cc -o test test.c -I/usr/local/include -L/usr/local/lib -llua -lm" generated the binary as expected. On another system (OpenSuse? 11.4, gcc4.7) -ldl was also needed to resolve undefined references to "dlopen" etc.
Finally, running the test you should get something like:
$ ./test The table the script received has: 1 2 2 4 3 6 4 8 5 10 Returning data back to C Script returned: 30
That should demonstrate how the basic API works and how values are passed between C and Lua.
For more, see [Lua API Demo]. It is a module designed for the Lua interpreter that allows you to set up a fake Lua state with a stack, call Lua API functions, and observe their effect on the stack.