2015-12-02 92 views
1

我想註冊一個Lua C模塊,我需要這樣使用。Lua C模塊:困惑包括成員

local harfbuzz = require 'harfbuzz' 

-- initialize blob 
local blob = harfbuzz.Blob.new(…) 
print(blob:length()) 

我的理解是,我要創建一個新表和元表添加到它與方法,然後添加該表作爲成員Blob到頂級LIB表。

這是我C文件中的相關代碼片段。我不太確定register_blob函數中包含哪些內容。我嘗試了一些東西,但他們沒有工作。

static const struct luaL_Reg blob_methods[] = { 
    { "length", blob_length }, 
    {"__gc", blob_destroy }, 
    { NULL, NULL }, 
}; 

static const struct luaL_Reg blob_functions[] = { 
    { "new", blob_new }, 
    { NULL, NULL } 
}; 

static const struct luaL_Reg lib_table [] = { 
    {"version", get_harfbuzz_version}, 
    {NULL, NULL} 
}; 

int register_blob(lua_State *L) { 
    // QUESTION: What should I include here 
} 

int luaopen_luaharfbuzz (lua_State *L) { 
    lua_newtable(L); 

    register_blob(L); 

    luaL_setfuncs(L, lib_table, 0); 

    return 1; 
} 

回答

2

register_blob做什麼完全取決於new_blob需要做什麼。兩者互相饋送。

鑑於您的用例,new_blob需要創建新對象,並且這些新對象具有等於您的blob_methods表的元表元。所以,new_blob需要做的是:

  1. 創建一個表/ userdata被返回。
  2. 將表/ userdata指定爲從blob_methods表的內容構建的metatable。
  3. 做任何其他需要對象的初始化工作。
  4. 返回對象。

那麼你register_blob代碼需要做的是建立您打算在步驟2中使用,那麼它存儲在某處是new_blob可以輕鬆地訪問它的元表。但也有人認爲沒有人可以。或者至少在C代碼之外沒有人。

Lua設計得很好,它有一個存儲這種數據的地方。它被稱爲Lua registry table。註冊表就像一個全局表。但它只能從C訪問; Lua代碼無法觸及它(除非您使用調試庫,或將註冊表傳遞給Lua)。

使用註冊表的習慣方式(據我所知)是每個C模塊在註冊表中指定它自己的表索引。因此您的luaopen_luaharfbuzz函數將創建一個表並將其存儲到註冊表中的一個鍵中。關鍵可能會有一些字符串,可能以您的模塊命名。你把你所有的私人東西放進桌子裏。

所以你register_blob功能會:

  1. 創建將用作元表爲blob對象表。
  2. 使用luaL_setfuncsblob_methods設置爲新創建的表格。
  3. 從註冊表中獲取harfbuzz表。
  4. 將新創建的表放入harfbuzz表中來自注冊表的已知密鑰中。

那樣,new_blob知道準確地去哪裏得到metatable使用。

+0

感謝您撰寫這樣一個全面的答案。 – vyom

+0

當然,您可以將註冊表傳遞給Lua:'lua_pushvalue(L,LUA_REGISTRYINDEX)'。這就是'debug.getregistry'所做的... – siffiejoe

+0

@siffiejoe:注意到並修復。 –