Luna Wrap |
|
LunaWrapFunc(function)that will generate a complete and minimal temporary function that can be pushed through e.g. LunaFive
LunaWrap comes with 5 files, that's why it's been packed into ZIP-Archive: [LunaWrap.zip] Note: I have copied all files out of my own project, that means I have not tested them standalone. That in turn means that it might not compile yet, but I will test and possibly fix all files ASAP.
LunaWrap::check( lua_State* state , int index ) behaves just like luaL_check* on an arbitrary type T. LunaWrap::lightcheck<T>( lua_State* state , int index , T fallback = T() ) checks whether the necessary value is at the stack position and returns it. If not, it returns the third parameter that specifies the fallback. LunaWrap::is_a<T>( lua_State* state , int index ) returns true, if the value at the supplied stack position is a T, false otherwise. By using LunaWrap::push( lua_State* state , ... ) you can push as many C++ types as you want through ..., while push() will always return the number of lua-values, that it pushed onto the stack. That way, you can easily do
int foo( lua_State* state ){ return LunaWrap::push( state , 5 , std::string("Hello World") , std::map<int,int>() );
The following example features the well-known Account-class. Notice how you don't have to write the Lua-"proxy"-functions anymore, since they are being generated for you by LunaWrap. By "proxy"-functions I mean the ones that take a lua_State*, read all the arguments for the C++ function off the lua-stack, call the actual C++-function and return the number of the values it returned (usually 1). You can really start using your C++ classes right away in Lua!
#include "Luna.h"
#include "LunaWrapFunc.h"
class Account
{
private:
int balance;
public:
Account() : balance( 0 ) {}
void deposit( int amount ){
if( amount >= 0 )
balance += amount;
}
int withdraw( int amount ){
if( balance < amount )
amount = balance;
balance -= amount;
return amount;
}
int balance() const {
return balance;
}
//! Lua!//
static const char className[];
static Luna<Account>::FunctionType methods[];
static Luna<Account>::PropertyType properties[];
};
const char Account::className[] = "Account";
Luna<Account>::FunctionType Account::methods[] = {
{ "deposit" , LunaWrapFunc( &Account::deposit ) },
{ "withdraw" , LunaWrapFunc( &Account::withdraw ) }
};
Luna<Account>::PropertyType Account::properties[] = {
{ "balance", LunaWrapFunc( &Account::balance ) , 0 } // Readonly property
};
If you really have a "proxy"-class, that is, the one you register through Luna and which actually only is a reference to the C++ Class your making available to lua, it's still possible to use LunaWrapFunc?: You only have to provide a cast-operator within proxy class to the actual class. Since that sounds way more diffuse than it is, let's have an example of that, too.
#include "Luna.h"
#include "LunaWrapFunc.h"
class StringRef : public std::shared_ptr<std::string>
{
public:
// Cast-operator to the string object this class "proxies"
operator string&(){ return *(*this) ); }
//! Lua!//
static const char className[];
static Luna<Account>::FunctionType methods[];
static Luna<Account>::PropertyType properties[];
};
const char StringRef::className[] = "StringRef";
Luna<StringRef>::FunctionType StringRef::methods[] = {
{ "front" , LunaWrapFunc( (char&(string::*)()) &string::front , StringRef ) }, // The cast is needed to disambiguate the const-version front() from the non-const version
{ "back" , LunaWrapFunc( (char&(string::*)()) &string::back , StringRef ) }, // Same here
{ "push_back" , LunaWrapFunc( (char&(string::*)()) &string::back , StringRef ) }
};
Luna<StringRef>::PropertyType StringRef::properties[] = {
{ "length" , LunaWrapFunc( &string::length , StringRef ) , 0 } // Readonly property
};