Simple Lua Api Example

lua-users home
wiki

This is a simple introductory example of how to interface to Lua from C. The C program loads a Lua script file, sets some Lua variables, runs the Lua script, and reads back the return value. The below example works with Lua 5.3.

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.


RecentChanges · preferences
edit · history
Last edited March 2, 2018 7:09 am GMT (diff)