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 };