Asymmetric coroutines do not
have this problem, because the resume
primitive does not affect the current
stack. There is still a restriction that a
program cannot yield across a C call—
that is, there cannot be a C function in
the stack between the resume and the
yield. This restriction is a small price to
pay for allowing portable coroutines in
Lua.
tion lua _ pushcfunction. Once created as a Lua function, this new value
can be manipulated just as any other
Lua value. The second added line in
the new code calls lua _ setglobal
to set the value on the top of the stack
(the new function) as the value of the
global variable getenv.
Besides being first-class values,
functions in Lua are always anonymous. A declaration such as
Data
One of the main problems with the
minimalist eval approach for an API
is the need to serialize all data either
as a string or a code segment that rebuilds the data. A practical API should
therefore offer other more efficient
mechanisms to transfer data between
the host program and the scripting environment.
When the host calls a script, data
flows from the host program to the
scripting environment as arguments,
and it flows in the opposite direction
as results. When the script calls a host
function, we have the reverse. In both
cases, data must be able to flow in both
directions. Most issues related to data
transfer are therefore relevant both for
embedding and extending.
To discuss how the Lua–C API handles this flow of data, let’s start with an
example of how to extend Lua. Figure
3 shows shows the implementation of
function io.getenv, which accesses
environment variables of the host program.
For a script to be able to call this
function, we must register it into the
script environment. We will see how
to do this in a moment; for now, let us
assume that it has been registered as
a global variable getenv, which can be
used like this:
with the stack containing only the ar-
guments given to getenv, with the first
argument at position 1 in the stack.
The first thing os _ getenv does is
to call luaL _ checkstring, which
checks whether the Lua value at posi-
tion 1 is really a string and returns a
pointer to the corresponding C string.
(If the value is not a string, luaL _
checkstring signals an error using a
longjump, so that it does not return to
os _ getenv.)
function inc (x) return x + 1 end
is syntactic sugar for an assignment:
inc = function (x) return x + 1 end
lua _ State *L = luaL _ newstate();
/* creates a new state */
luaL _ openlibs(L);
/* opens the standard libraries */
+ lua _ pushcfunction(L, os _ getenv);
+ lua _ setglobal(L, “getenv”);
print(getenv(“PATH”))
The first thing to note in this code
is the prototype of os _ getenv. The
only parameter of that function is a
Lua state. The interpreter passes the
actual arguments to the function (in
this example, the name of the environment variable) through a data structure inside this state. This data structure is a stack of Lua values; given its
importance, we refer to it as the stack.
When the Lua script calls getenv,
the Lua interpreter calls os _ getenv
The first added line is all the magic
we need to extend Lua with host func-
tions. Function lua _ pushcfunc-
tion receives a pointer to a C func-
tion and pushes on the stack a (Lua)
function that, when called, calls its
corresponding C function. Because
functions in Lua are first-class values,
the API does not need extra facilities
to register global functions, local func-
tions, methods, and so forth. The API
needs only the single injection func-
The API code we used to register
function getenv does exactly the same
thing as a declaration in Lua: it creates
an anonymous function and assigns it
to a global variable.
Figure 3. A simple C function.
static int os_getenv (lua_State *L) {
const char *varname = luaL_checkstring(L, 1);
const char *value = getenv(varname);
lua_pushstring(L, value);
return 1;
}