2015-12-02 55 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:注意到并修复。 –