親自動手進行 Cpp 綁定 |
|
以下提供一些我發現的技巧,大多以程式碼形式呈現,這些技巧會一起運作
lauxlib 具有用來處理資料使用者元表的極有用的函數。這些函數在參考手冊的 [Lua 輔助函式庫] 中有充足的說明。我建議每個元表的名稱與類別名稱相同;這樣可以進行有趣且不懷好意的預處理器技巧,例如以下所述。對於不熟悉運算子的讀者來說,#define 陳述式中的 # 運算子會在巨集展開時,將下一個參數置於引號中。
一個有用的巨集,用來簡化檢查指定堆疊位置的物件是否為指定使用者資料類型 (已利用 luaL_newmetatable 註冊) 的程序
#define lua_userdata_cast(L, pos, T) static_cast<T*>(luaL_checkudata((L), (pos), #T))
我在自己的元方法中大量使用類似這樣的內容
if(const MyClass* myclass = lua_userdata_cast(L, 1, MyClass)) { MyClass->SomeMethod(); return 0; }
深入了解
void* operator new(size_t size, lua_State* L, const char* metatableName) { void* ptr = lua_newuserdata(L, size); luaL_getmetatable(L, metatableName); // assert(lua_istable(L, -1)) if you're paranoid lua_setmetatable(L, -2); return ptr; } #define lua_pushobject(L, T) new(L, #T) T
現在,停止執行 boxpointer 異常,若要將元表利用 luaL_newmetatable 建立的類型物件推送到堆疊中,請依下列方式進行
lua_pushobject(L, MyClass)(arg1, arg2, arg3);
... 如此一來,您可以直接在它將使用的記憶體區塊中建構新的 MyClass
!
注意一下
template<typename T> int GCMethod(lua_State* L) { static_cast<T*>(lua_touserdata(L, 1))->~T(); return 0; }
此範本化方法構成完美的 __gc 方法。如下所示
lua_pushstring(L, "__gc"); lua_pushcfunction(L, GCMethod<MyClass>); lua_settable(L, 1);