Lua 中赋值覆盖的问题
我正在一个嵌入式环境/MCU 中使用 Lua v5.2.2。
我需要在 Lua 中暴露一些“参数”,用于直接访问硬件(因此需要调用 C 函数)进行读取和写入。然而,我正在寻找其他实现方式,而不是使用普通的 getter 和 setter。
我主要是在探索 Lua 的元编程能力,但我也相信我可以为用户创建一个更简单的接口。
我想要实现的行为是以下这样的:
my_param = createParameter {name="hw_param1", type="number", min=0, max=100}
my_param = 5
result = my_param + 3
在第一行中,创建一个新的参数。这是一个对 C 函数的调用。使用适当初始化的结构将 userdata 推送到栈中。必要时也会初始化硬件。返回一个新的 table。
第二行对参数对象进行赋值。我希望这会调用一个带有单个参数的 C 函数(分配的参数),以便将值存储到硬件寄存器中。
在第三行中,读取了参数。我再次需要调用向硬件寄存器获取参数值的 C 函数,并返回结果。
请注意,该参数的实际值可能在 Lua 的范围之外发生更改,因此在初始化期间仅读取一次该值是不正确的。必须每次调用 C 函数以获取实际值。类似地,对值的写入必须立即导致对硬件的写入。
如何实现?具体而言,我可以改变参数的元表来实现第 2 和第 3 行吗?(我知道如何实现第 1 行)。
此外,从构造函数返回一个 table 是否有必要?例如,我可以返回一个原始的 Lua 类型(如数字),它将像上面一样运作吗?
是的,你可以修改元表的元方法。
第二行代码会完全改变该变量所持有的值。
但是,如果你设置参数对象中的一个字段,比如 my_param.x = n,这将会调用 __newindex 元方法;你可以重写这个元方法来按照你需要的方式进行操作。在你的情况下,你将需要使用一个 C 函数调用来设置参数的字段并更新它。
关于第三行代码,同样的原理依旧适用,只需要使用 __add 元方法,然后在 __add 被调用时对对象进行操作即可。
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的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 代码?

这不完全是你要求的,但很接近:
function createParameter(t) param = {} param.data = t backingTable = {} metatable = {} function metatable.__index(t, k) --如果你想要拦截值并将其传递给你的 C 函数,可以在此处进行拦截。 return backingTable[k] end function metatable.__newindex(t, k, v) --如果你想要拦截值并将其传递给你的 C 函数,可以在此处进行拦截。 backingTable[k] = v end setmetatable(param, metatable) return param end -------------------------------------------------------- my_param = createParameter{name=“hw_param1”,type=“number”,min=0,max=100} my_param.value = 5 result = my_param.value + 3 print(result) --打印 8 print(my_param.data.name) --打印 hw_param1你可能可以通过给全局表
_G分配元表来实现一些诡计,但我认为这将有些棘手,可能会导致意想不到的结果。编辑:
如果你真的讨厌必须在层次结构中使用,而且你真的想直接设置它,那么你可以通过设置全局表来实现。
globalMetatable = {} globalParamNames = {} globalParams = {} function globalMetatable.__index(t, k) if globalParamNames[k] then --如果你想要拦截值并将其传递给你的 C 函数,可以在此处进行拦截。 print("Read from param " .. k) return globalParams[k] else rawget(_G, k) end end function globalMetatable.__newindex(t, k, v) if globalParamNames[k] then --如果你想要拦截值并将其传递给你的 C 函数,可以在此处进行拦截。 print("Wrote to param " .. k) globalParams[k] = v else rawset(_G, k, v) end end setmetatable(_G, globalMetatable) function createParameter(t) globalParamNames[t.varname] = true end -------------------------------------------------------- createParameter{varname="my_param", name="hw_param1", type="number", min=0, max=100} my_param = 5 result = my_param + 3 print(result) --打印 8 print(my_param) --打印 5