Talking With Lua
Making it easier for C++ to speak Lua
Introduction
There are a lot of libraries and source code out there for binding, to Lua, C++ functions and methods, and some do classes. I haven't found so much, although some is out there, for working the other way. In other words, to make it easier to call Lua functions, and manipulate values held in the Lua state. Here is what I've written for this purpose. I've made this page and uploaded the code in the hope will be useful to someone. It has been influenced from reading and using other's code, namely LuaBind's object class. I eventually found some code (for Lua 3.1) that was very similar to what I had written, yet different enough to give me some more good ideas. It works with references (luaL_ref), so values that are 'held' by C/C++ do not get garbage collected.
It works well along side LuaBridge, with a two liner helper function, when calling Lua functions with class instances as parameters.
If you find this useful I'd love to hear about it. suprapilot+LuaCode@gmail.com
Example Usage
Creating a table, and adding elements.
void createTable( lua_State *L )
{
// Create a new table, add some elements.
LuaRef myNewTable( L );
myNewTable.createTable( "MyTable" );
myNewTable[1] = 10;
myNewTable[2] = 20;
myNewTable[3] = 30;
myNewTable["text"] = "Hello World!";
}
Calling a Lua function.
void callPrint( lua_State *L )
{
LuaRef print( L, "print" );
std::string world( "world!" );
LuaRef val( L, "Any Lua Object" );
print( 10, "Hello", world, val ); // You can use only types that have conversions to the class LuaVal.
}
Manipulate a Lua object.
void accumulate( lua_State *L, int increment )
{
LuaRef counter( L, "myCounter" ); // Intialize from "myCounter"
counter = counter + increment;
counter.store( "myCounter" ); // This assigns the value that we have a reference for, to "myCounter".
}
Catch any errors thrown and report to console.
void catcherrors( lua_State *L )
{
try
{
LuaRef table( L );
table.createTable();
table(); // Try and call a table as a function...
}
catch( LuaException &e )
{
std::cerr << e.what() << std::endl;
}
}
Chaining of Lua calls
void chain( lua_State *L )
{
// Assume 'add' and 'sub' are already defined in the Lua state.
// Of course you would normally only do this for larger Lua functions
// where the overhead compared to the work done is less.
LuaRef func1( L, "add" );
LuaRef func2( L, "sub" );
LuaRef ret;
ret = func1( func2( 5, 2 ), 10 );
std::cout << ret << std::cout;
}
Lua Bridge Glue
This code and LuaBridge will happily co-exist. You can even call functions referenced by a LuaRef with instances of bound classes. You first however need to convert the LuaBridge shared pointer to a LuaRef...
template<typename T>
LuaRef *convertPtrToLuaRefPtr( shared_ptr<T> ptr )
{
luabridge::tdstack<T>::push( ptr ); // Puts the class instance on top of Lua stack
fromStack fs( L );
return new LuaRef( fs ); // Creates a reference to instance and removes from the Lua stack.
}
or if you prefer...
template<typename T>
LuaRef convertPtrToLuaRef( shared_ptr<T> ptr )
{
luabridge::tdstack<T>::push( ptr ); // Puts the class instance on top of Lua stack
fromStack fs( L );
return LuaRef( fs ); // Creates a reference to instance and removes from the Lua stack.
}
Any suggestions, or comments are welcome, see my email below.
