Luna Wrap |
|
LunaWrapFunc(function)這將產生一個完整且最小的暫時函式,可透過例如 LunaFive 推送
LunaWrap 附帶 5 個檔案,因此已打包到 ZIP 檔案中:[LunaWrap.zip] 注意:我已將所有檔案複製出自己的專案,這表示我尚未單獨測試它們。這反過來表示它可能無法編譯,但我將盡快測試並修正所有檔案。
LunaWrap::check( lua_State* state , int index ) 在任意型別 T 上的行為就像 luaL_check*。LunaWrap::lightcheck<T>( lua_State* state , int index , T fallback = T() ) 會檢查堆疊位置上是否為必要的數值,然後回傳它。如果不是,它會回傳指定預設值的第三個參數。LunaWrap::is_a<T>( lua_State* state , int index ) 會回傳 true(如果提供的堆疊位置上的數值是 T)或 false(反之)。透過使用 LunaWrap::push( lua_State* state , ... ),您可以透過 ... 推送任意數量的 C++ 型別,而 push() 會永遠回傳堆疊上已推入的 lua 值數。這樣,您可以輕鬆地執行
int foo( lua_State* state ){ return LunaWrap::push( state , 5 , std::string("Hello World") , std::map<int,int>() );
下列範例具備廣為人知的 Account 類別。請注意,您不再需要撰寫 Lua「代理」函式,因為它們會由 LunaWrap 為您產生。這裡所說的「代理」函式是指那些會使用 lua_State*、從 lua 堆疊上讀取 C++ 函式的所有參數、呼叫實際 C++ 函式並回傳它回傳的值個數(通常為 1)的函式。您真的可以立刻在 Lua 中開始使用您的 C++ 類別!
#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 };
如果您真的有一個「代理」類別,也就是說,您透過 Luna 註冊的一個類別,而它實際上只是一個您提供給 lua 的 C++ 類別的參考,則仍然可以使用 LunaWrapFunc?:您只需在代理類別中提供一個轉型運算子,轉換至實際類別。由於那聽起來比實際情況要更模糊,因此我們也提供一個範例來說明。
#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 };