親自動手進行 Cpp 綁定

lua-users home
wiki

在編寫我的遊戲引擎,特別是從一開始就整合 Lua 時,我考慮了一些綁定產生器,例如 SWIG、tolua、SimplerCppBinding 等。但沒有一個可以充分滿足我的需求

以下提供一些我發現的技巧,大多以程式碼形式呈現,這些技巧會一起運作

建立元表

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

placement new 以避免裝箱指標

深入了解

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

範本化 __gc 方法

注意一下

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

請參閱


RecentChanges · 偏好設定
編輯 · 歷程記錄
最後編輯時間為 2014 年 2 月 23 日格林威治標準時間下午 5:22 (相異處)