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 theexample
executable. - Use the command
./example
to run theexample
executable. - Read
example.c
andexample.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
).
- The Lua stack (created by
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 functionscalbn
.math.remquo
, which takes two numbers and returns two. Implement it by wrapping the C functionremquo
.
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 oflua_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.
- If the user does not provide an
argument, the Lua function should produce an error via
- 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.
- You can write this code in the
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
!