Programming in Lua | ||
Part IV. The C API Chapter 24. An Overview of the C API |
24.2 - The Stack
We face two problems when trying to exchange values between Lua and C:
the mismatch between a dynamic and a static type system
and the mismatch between
automatic and manual memory management.
In Lua, when we write a[k] = v
,
both k
and v
can have several different types
(even a
may have different types,
due to metatables).
If we want to offer this operation in C, however,
any settable
function must have a fixed type.
We would need dozens of different functions for this single operation
(one function for each combination of types for the three arguments).
We could solve this problem by declaring some kind of union type in C,
let us call it lua_Value
,
that could represent all Lua values.
Then, we could declare settable
as
void lua_settable (lua_Value a, lua_Value k, lua_Value v);
This solution has two drawbacks.
First, it can be difficult to map
such a complex type to other languages;
Lua has been designed to
interface easily not only with C/C++,
but also with Java, Fortran, and the like.
Second, Lua does garbage collection:
If we keep a Lua value in a C variable,
the Lua engine has no way to know about this use;
it may (wrongly) assume that this value is garbage
and collect it.
Therefore, the Lua API does not define
anything like a lua_Value
type.
Instead, it uses an abstract stack to exchange values between Lua and C.
Each slot in this stack can hold any Lua value.
Whenever you want to ask for a value from Lua
(such as the value of a global variable),
you call Lua, which pushes the required value on the stack.
Whenever you want to pass a value to Lua,
you first push the value on the stack,
and then you call Lua (which will pop the value).
We still need a different function to push each C type on the stack
and a different function to get each value from the stack,
but we avoid the combinatorial explosion.
Moreover, because this stack is managed by Lua,
the garbage collector knows which values C is using.
Nearly all functions in the API use the stack.
As we saw in our first example,luaL_loadbuffer
leaves its result on the stack
(either the compiled chunk or an error message);lua_pcall
gets the function to be called from the stack
and leaves any occasional error message there.
Lua manipulates this stack in a strict LIFO discipline
(Last In, First Out; that is, always through the top).
When you call Lua, it only changes the top part of the stack.
Your C code has more freedom;
specifically, it can inspect any element inside the stack
and even insert and delete elements in any arbitrary position.
Programming in Lua |
No comments:
Post a Comment