To get a feeling of how the library is used, let's write a simple example program. It will be line interpreter working with standard input stream, with support of fixed-size numeric arrays. We assume that Lua and Lua-API++ are already set up in our project.
First, we start with the interpreter part. The State object will create Lua state and interpret strings.
#include <iostream>
void interpretLine(
State& state,
const string& line)
{
try {
} catch(exception& e) {
cerr << e.what() << endl;
}
}
void interpretStream(
State& state, istream& in)
{
string currentLine;
while(!in.eof()) {
getline(in, currentLine);
interpretLine(state, currentLine);
}
}
int main(int argc, const char* argv[])
{
interpretStream(state, cin);
}
With this part done, we can add support of arrays. We will use vector
of double
as underlying native type. The simple Lua interface of our arrays will be as follows:
- global Lua function
createArray
will create array objects of given size;
- array objects will be accessed with integer indices for reading and writing elements;
- wrong index will produce an error;
- length operator will return amount of elements in the array.
We can salvage some of the functions vector
already has, so we need only to register userdata and write a couple of functions.
#include <vector>
using dvec = vector<double>;
dvec aCreate(unsigned int size)
{
return dvec(size);
}
void aDestroy(dvec& self)
{
self.~dvec();
}
void aWrite(dvec& self, unsigned int index, double val)
{
self.at(index) = val;
}
Now we are ready for the final step: setting up the environment. It will require two things: associate metatable with dvec and define array-creating function. The function that does it needs access to Lua state, so it has to be LFunction.
{
"__index", static_cast<double& (dvec::*)(size_t)>(&dvec::at),
"__newindex", aWrite,
"__len", dvec::size,
"__gc", aDestroy
);
c.
global[
"createArray"] = aCreate;
}
This setup function will have to be called from main() by State object, so it will need to be transformed into Lua compatible C function with mkcf template. Here is the final result:
#include <iostream>
#include <vector>
using dvec = vector<double>;
dvec aCreate(unsigned int size) { return dvec(size); }
void aDestroy(dvec& self) { self.~dvec(); }
void aWrite(dvec& self, unsigned int index, double val) { self.at(index) = val; }
{
"__index", static_cast<double& (dvec::*)(size_t)>(&dvec::at),
"__newindex", aWrite,
"__len", dvec::size,
"__gc", aDestroy
);
c.
global[
"createArray"] = aCreate;
}
void interpretLine(
State& state,
const string& line)
{
try {
} catch(exception& e) {
cerr << e.what() << endl;
}
}
void interpretStream(
State& state, istream& in)
{
string currentLine;
while(!in.eof()){
getline(in, currentLine);
interpretLine(state, currentLine);
}
}
int main()
{
interpretStream(state, cin);
}