Lua-API++  2015-02-12-3
Lua-API++ library
Basic concepts

Lua API++ is built on several basic concepts explained in this section. The namespace lua is omitted from expamples.

Global state

The State class represents a Lua context through RAII idiom. Besides maintaining life-cycle of the context, State object can also execute files, strings and Lua-compatible functions, which is useful for setting up the environment.

Lua functions and context

This library maintains a specific format for functions exposed to Lua:
Retval someFunction(Context& context);
Automatic stack management requires function to return specific kind of value, Retval, which can be used to return arbitrary number of values. The Context object gives access to function's local and global Lua context, as well as access to most of API features that are not directly associated with values. Through Context you gain access to function's arguments, global values, registry, upvalues, garbage collector etc. It is also used for returning values and reporting errors. Function that conforms to this specification can be automatically promoted to Lua or can be explicitly wrapped into C-function via mkcf function using function's name as template parameter. Normal, non-compliant C functions also can be automatically promoted or wrapped explicitly with wrap function.

Multiple return values

Returning multiple values

You can return an arbitrary number of values inside Retval object created with a call to ret method of Context object:

using namespace lua;
Retval give123(Context& c){
return c.ret(1, 2, "3");
}

In order to return an arbitrary number of values, accumulate them in a Valset and return it:

using namespace lua;
Retval makeSequence(Context& c){ // create a sequence of natural numbers
const unsigned int amount = c.args.at(0); // First argument of function is sequence size
Valset rv(c);
for(auto i = 1u; i <= amount; ++i)
rv.push_back(i);
return c.ret(rv);
}

Accepting multiple return values of a call

The results of a call can be handled in four ways: discarded completely, used as a single value, used as a sequence of values or saved in a Valset object. Using the results of a call as a single value happens in context where single value is assumed: index, assignment etc. Contexts that assume a sequence of values, such as function call parameters or returning values, will automatically expand multiple values into a subsequence. In order to store an arbitrary number of return values on Lua stack for further processing, create a Valset object by assigning call results to it:

using namespace lua;
Retval receiveMultiret(Context& c){
Valset results = c.global["give123"](); // Call global function
assert(results.size() == 3);
assert(results[1] == 2);
return c.ret();
}
Note
Valset objects are expanded just like call results, but they cannot be used as a single value.

Lua values

Lua values, as opposed to native values, are values stored inside Lua state. They are handled with value-objects, which incapsulate all available operations over values. In this documentation, "value" means a value-object unless specified otherwise. Values can be indexed with [] and called with () to same effect as in Lua code, producing another value(s). Arithmetic operations (not available in Lua 5.1 compatibility mode) with value-objects is done with Lua and produces yet another value-object.
Concatenation is supported with the & operation, chain concatenations being optimized into a single operation.
Comparisons of value-objects is done through Lua, but produces native boolean values.
The Valref class documents all operations avaliable for value-object. Though there are other types of value-objects, referred to as Temporary, they have same interface as Valref.

Native values

Native values are values that are used immediately in C++ code. The library recognises several basic types as native, including bool, int, unsigned, float, double, const char* and std::string. Native values of supported types can be implicitly promoted to Lua values when used in a context that expects a Lua value: function parameters, indices, operands etc. Lua values can be converted to appropriate native type implicitly or explicitly with cast or to methods. This documentation refers collectively to anything that is or can be promoted to Lua value as Valobj.

User values

Lua API++ library supports user-type handling in a minimally intrusive way. Objects of type that is bound as user-data with LUAPP_USERDATA macro are recognised as such and can be implicitly promoted to Lua values. Lua values can be converted to reference to user type explicitly, using cast method.

Be sure to assign individual metatables to all userdata types when initializing environment: metatables are used to identify userdata properly. Casting to userdata without assigned metatable will always fail. When a new userdata is created, it is automatically assigned corresponding metatable.

Temporary value handling

This documentation includes numerous references to Temporary type.

The Lua values may be stored in different places: stack, global variables, upvalues, registry etc. Even more important, they could be temporary results of some operations, which means they do not exist at all before the operation and must be discarded after use. Their creation may require yet more temporary values.

To handle such cases and free you from managing the stack manually, this library uses special proxy types constructed via templates. You do not need to know their exact types, because they behave just like Valref.

Valref

The Valref type represents a reference to an existing anchor object. It is safe to pass around as long as it doesn't outlive the anchor object it references.

Anchor value types

Anchor types provide permanent residence for Lua values (that is, anchor object reserves one or several stack slots for itself for as long as it exist). They "anchor" a value to the stack for future reference, hence such a name.

Value

The Value type represents a single Lua value on the stack. This type is intended to be used to anchor result of some cumbersome operation for subsequent use without repeating that operation again. Because Value object represents more an anchor to a position in stack rather than its content, the actual value at that position can be replaced at any time with simple assignment. The only difference with Valref is that a Value object is considered a new entity and when Value object expires, the referenced slot is removed from the stack.

Table

The Table type represents a single specific subtype of Lua value: a table. This type has reduced set of available operations, leaving only those applicable to tables, but in addition it has raw access and allows to iterate over the contents.

This type also has static functions, array and records that create filled table with the values you provide.

Valset

The Valset object represents a contiguous set of values on the stack. The main purpose of this type is to hold multiple values returned from function call, also it captures the success status of protected calls. The arguments for the function are also represented as a read-only Valset object. It is possible to grow or shrink Valset gradually in order to collect an arbitrary number of values, and returning single Valset from function is a special case: contents of the set is used directly rather than being copied.