ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


Introducing Lua
Pages: 1, 2, 3

Eventually it will be useful to provide more than global variables for users to manipulate. Extending Lua so that there's an available API, tailored to your program, provides an increased level of flexibility for the user. One thing to keep in mind is that the Lua runtime library contains an excellent supply of sample code to review.



Every Lua extension function written in C has the same signature. It accepts a Lua context object, traditionally called L, and then returns an integer that indicates the number of return values. (Lua functions can return more than one value.) You can obtain parameters and return values through a simple stack-based API that operates on the context object. The API provides the ability to push and pop any of the Lua data types off or on the stack. There is also a set of API functions for manipulating tables (passed by reference) and strings.

To show off extending Lua, here's an example that makes the gethostbyaddr function, which returns information about TCP/IP hostnames given an IP address, available in Lua. In C, the gethostbyaddr function returns a hostent struct. The members of that struct include the hostname, the address type, the size of the address, any aliases associated with the hostname, and some other information. The Lua function takes a host address as a dotted decimal string and returns two values, the primary hostname and an array of host aliases. It could instead return a single table duplicating the hostent struct, but this provides a simpler and hopefully clearer example.

The code takes the host address off of the stack (the first parameter). Then it calls the C version of gethostbyaddr. Finally, it pulls out the fields of the struct and places them on the stack as return values.

/* Return a hostname and a table of aliases given an IP 
 * address in dotted decimal notation */
static int l_gethostnames(lua_State *L)
{
  /* Obtain our argument and verify that it is a string */
  const char *addr = luaL_checkstring(L,1);

  /* Convert the argument into the addr gethostbyaddr expects */
  unsigned long iaddr = inet_addr(addr);

  /* We'll return a table starting at t[1] in the lua style */
  int tableIndex = 1;
  
  /* Make the call to gethostbyaddr */
  struct hostent *h = gethostbyaddr((char *)&iaddr,sizeof(iaddr),AF_INET);

  if (!h) {
    /* If gethostbyaddr fails, we'll just return two nils */
    lua_pushnil(L);
    lua_pushnil(L);
  } else {
    /* gethostbyaddr has returned a value.  Push the primary name */
    lua_pushstring(L,h->h_name);
    
    /* Now, create a table.  So far we've pushed a string
     * and an empty table on the stack */
    lua_newtable(L);

    /* Loop over the aliases if any and put them in the table we've
     * created on the stack.  Remember to adjust the indices between Lua and C
     */
    while (h->h_aliases[tableIndex - 1]) {
      /* First we push the key and the value for this table entry on
       * the stack.
       */
      lua_pushnumber(L,tableIndex);
      lua_pushstring(L,h->h_aliases[tableIndex - 1]);

      /* lua_settable takes the last two items on the stack and 
       * treats them as a key,value pair.  This pair is added 
       * to the table at index.  Negative indices are back from the 
       * top of the stack. In this case the key is at -2, the value at
       * -1 and the table we create with lua_newtable is at -3
       */
      lua_settable(L,-3);
      tableIndex++;
    }
  }

  /* Through either path we've left two items on the stack to 
   * return. */
  return 2;
}

Add calls to lua_pushcfunction(L,l_gethostnames); lua_setglobal(L,"gethostnames"); somewhere after initializing the Lua interpreter to make the gethostnames function available from Lua.

Conclusion

At this point, you have a reasonable idea of what the Lua language is like. You also have seen how readily you can integrate it into your application. If you're interested in pursuing Lua, you should avail yourself of these resources. First and most importantly, spend some time with Roberto Ierusalimschy's book Programming in Lua, which is available both as a printed volume and for free online. This excellent resource goes well beyond the Lua Reference Manual and illuminates the language and its use very effectively. The Lua user community provides excellent resources including a wiki and a mailing list. Finally, LuaForge is an online repository of Lua-based projects and libraries.

Keith Fieldhouse is a software developer and writer living in upstate New York with his wife and two young daughters.


Return to ONLamp.com.



Sponsored by: