Lua从C中注册metatable的问题
2011-2-23 13:52:37
收藏:0
阅读:228
评论:2
你好,我有下面的代码,它似乎能工作,但我不确定为什么 - 我构建了一个 testclass 如下
class testclass {
int ivalue;
public:
int getivalue();
void setivalue(int &v);
};
然后注册 testclass(实际函数的一些位被省略了,但它们相当基本)。我不理解的是注册 metatable 的部分。(setivalue 和 getivalue 是调用同名类函数的 c 函数)
static const struct luaL_Reg arraylib_f [] = {
{"new", new_testclass},
{NULL, NULL}
};
static const struct luaL_Reg arraylib_m [] = {
{"set", setivalue},
{"get", getivalue},
{NULL, NULL}
};
int luaopen_testclass (lua_State *L) {
luaL_newmetatable(L, "LuaBook.testclass");
lua_pushvalue(L, -1); /* duplicates the metatable */
lua_setfield(L, -2, "__index");
luaL_register(L, NULL, arraylib_m);
luaL_register(L, "testclass", arraylib_f);
return 1;
}
我不理解的是,我将函数添加到 metatable 的 __index 中,但是当我运行
a = testclass.new()
a:set(10)
print(a:get())
它就像预期的那样工作。我不明白的是,为什么 set 被调用,我认为我已将其加载到 __index metatable 中了?这是我做的还是其他什么东西?
谢谢回答。
点赞
用户614701
如果我理解你的问题正确,你正在问set() get() 是如何通过__index元方法调用的。
该代码可以用纯lua表达:
local o = {}
function o.get(self)
return self.ivalue
end
function o.set(self, val)
self.ivalue = val
end
a = {}
mt = {
__index = function(t, n)
return o[n]
end
}
setmetatable(a, mt)
print(a:get())
a:set(10)
print(a:get())
结果:
nil
10
在这个例子中,mt表被设置为a表的元表。由于a表中既没有get表项也没有set表项,因此__index元方法被用于get和set。
如果将这个例子改成这样:
local o = {}
function o.get(self)
return self.ivalue
end
function o.set(self, val)
self.ivalue = val
end
a = {}
function a.get(self)
print('here')
return self.ivalue
end
mt = {
__index = function(t, n)
return o[n]
end
}
setmetatable(a, mt)
print(a:get())
a:set(10)
print(a:get())
结果:
here
nil
here
10
在这种情况下,get()不会调用__index元方法,因为a表已经存在get索引。
使用元方法可以创建许多有趣的结构,一旦你理解了它们的工作原理。我建议阅读13.4.1-在PiL中使用__index元方法 并且进行一些其他例子的实践。所有上述操作也可以通过_c api_完成。
2011-02-23 15:20:41
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
int luaopen_testclass (lua_State *L) { luaL_newmetatable(L, "LuaBook.testclass"); // 将新的元表留在栈中 lua_pushvalue(L, -1); // 在栈中有两个元表的“副本” lua_setfield(L, -2, "__index"); // 弹出其中的一个并将其赋值给第一个元表的 __index 字段 luaL_register(L, NULL, arraylib_m); // 在元表中注册函数 luaL_register(L, "testclass", arraylib_f); // 注册 testclass 类型的函数 return 1; }这段代码相当于下面的 Lua 代码:
metatable = {} metatable.__index = metatable metatable.set = function() --[[stuff--]] end metatable.get = function() --[[stuff--]] end我认为
new_testclassC 函数会为返回的表格设置元表 "LuaBook.testclass"。在你的代码中,你没有将函数添加到元表的
__index字段中。相反,你将指向元表的指针分配给了那个元表的名为__index的字段,并将set和get函数注册到其中。现在,如果你将该元表设置为从 'new_testclass' 函数返回的值(我认为你这样做了)——我们将其称为 'foo',然后调用
foo:set(10),那么 Lua 将会:__index字段——发现它是一个表__index字段的表中是否有一个名为 'set' 且值为函数的字段我希望这会帮助你理解这里发生了什么。