Part 1: Understand Lua embedding (30%)

Overview

This part of the assignment is a warmup. We will forget about script for a moment and focus on how to get Lua and C to talk to one another.

The code you write for this part will not be used directly in enhancing script, but the experience you gain doing this part will give you familiarity with the concepts involved (working with an embedded Lua interpreter), which will make doing the rest of the assignment much more straightforward.

Build, run, and understand the example executable

The Lua programming language provides an Application Programming Interface (API)—which is just a fancy name for a C library—that allows a C program to interoperate with a Lua program. In this part of the assignment, we will familiarize ourselves with the more important elements of the API.

In the files example.c and example.lua you will find some examples that show how to write C and Lua code that can call one another in the same program.

  • Use the command make example to build the example executable.
  • Use the command ./example to run the example executable.
  • Read example.c and example.lua carefully so that you understand how to call Lua from C, update Lua variables from C, and call C from Lua. You will want to use the Lua API documentation, which is your most important resource for this assignment. In particular, read about:
    • The Lua stack (created by luaL_newstate), which the C code uses to pass values to Lua and retrieve values from Lua.
    • API elements that allow C code to register C functions as callable from from Lua (e.g., lua_register) and that allow C code to call Lua functions (e.g., lua_call, lua_getglobal, lua_push*, lua_pop*)
    • API elements that allow C code to read, create, and write Lua values (e.g,. lua_to*, lua_newtable, lua_rawset).

To check your conceptual understanding, trying running the example Lua program on its own (with lua example.lua). You will see that it quits with an error. Why, and why does it run without error if we use ./example? (You don’t have to write up or turn in your answers, but if you’re not sure about your answers, talk with a grutor or prof. or post on Piazza.)

Make C math functions available to Lua

The built-in Lua math table contains a number of useful mathematical functions (e.g., math.sin and math.sqrt), but several useful functions from the C math library are not available, including tgamma, lgamma, log1p, and scalbn. As you have seen, we can wrap any C function and provide it to Lua, so that Lua code can call it. We can also write entries to Lua tables from C. Now we will put these pieces together to make C math functions available to Lua.

1. Call math.tgamma from Lua

The provided example.c wraps the C math-library function tgamma, so that it can be called from Lua.

Your task: Modify example.lua’s testit function so that it calls math.tgamma. For example math.tgamma(5) should give the result 24.

2. Write a fact function in Lua

Your task: In example.lua, write a function fact, that calls math.tgamma (on the basis that $n! = \Gamma(n+1)$). Your Lua function can assume that the input is a nonnegative number. Show that it works by extending the testit function to print out a factorial.

3. Add more C math functions to Lua

Your task: Following the example of math.tgamma, add add these functions to Lua:

  • math.scalbn, which takes two numbers and returns one. Implement it by wrapping the C function scalbn.
  • math.remquo, which takes two numbers and returns two. Implement it by wrapping the C function remquo.

Be sure that lscript.c adds each function to Lua’s math table. Here are some additional notes:

  • To write a C function that wraps a C math-library function, use lc_tgamma as a guide.
    • If the user does not provide an argument, the Lua function should produce an error via lua_error. If the user provides too many arguments, the extra arguments should be silently ignored.
    • This task requires not a lot of effort or special code from you, especially if you use the luaL_check* functions (instead of lua_to* functions). See the Lua Reference Manual for details.
    • Be careful if you copy-paste code from lc_tgamma, the number and types of arguments are different for each function, as are the number of values they return.
  • To add the math function to Lua’s math table:
    • You can write this code in the main function, guided by the existing code for modifying the table.
    • Be sure you add the function to Lua’s existing math table, not to a new table or as a globally available function.

Make sure you are getting and returning the Lua arguments in the right order, and that inputs and output don’t have to be integers (e.g., in Lua, math.remquo(10.3,4.5) should return quotient 2 followed remainder 1.3). Make sure that your C code gets the arguments in the right order, and allows the Lua code to pass floating-point numbers rather than just integers.

4. Write Lua code that uses the new functionality

Your task: In example.lua, write a function calc that:

  • takes a string and three additional arguments of all different types
  • performs some calculation using all of the arguments
  • returns two numbers as its result.

What calc does and how meaningful it is is up to you. It can print out information about what it calculates, if you like.

4. Call calc from example.c.

Your task: In example.c call your Lua function calc (either by writing straight-line code to push the arguments and do the call to calc, or by encapsulating this push-and-call code into a C “wrapper” function) and print the results.

With some experience connecting C and Lua, you are ready to move on to the next part: embedding Lua in script!