C 函数中如何保存 Lua 的数据(2)

简介: C 函数中如何保存 Lua 的数据(2)

二、上值

每一次在 Lua 中创建新的 C 函数时,可以将任意数量的上值和这个函数相关联,而每个上值都可以保存一个 Lua 值。后面调用该函数时,可以通过伪索引自由的访问这些上值。这种 C 函数与其上值的关联称为闭包。

 

上值的个数有限制, C 语言函数中最多可以有 255 个上值,lua_upvalueindex 的最大索引值是 256 。

1、如何为闭包添加上值

这里结合一个例子讲解,我们创建一个 C++ 函数给 Lua 调用,这个 C++ 函数是一个累加的闭包,每次调用都会产生新的值,而且每个闭包的值互不影响。

第一步,创建累加的 C 函数。

 

函数 newCounter:创建闭包的函数,每次 Lua 中调用 newCounter 函数,都会返回一个新的闭包,会携带新的上值。

函数 counter :真正的执行函数,每次 Lua 执行 newCounter 创建后的闭包都会运行该函数,该函数会 “更新上值以便下次使用” 和 “返回更新后的上值”。

image.png

第二步:将上述函数以库的形式添加到 Lua 中

image.png

image.png

第三步:编写 Lua 文件,并运行

Lua 中创建两个累加器,a 累加器累加三次,b 累加器只累加一次,可以从运行结果看出,两个累加器互不影响。

image.png

运行代码

image.png

运行结果

image.png

2、lua_pushcclosure

image.png

描述:

将一个 C 函数作为闭包压入 Lua 栈中。

参数:

· 参数 L: Lua 状态机指针。

· 参数 fn: 一个 C 函数指针,表示要作为闭包压入 Lua 栈的函数。

· 参数 n: 一个整数,表示闭包所使用的上值数量。

3、lua_upvalueindex

image.png


描述:

他是一个宏,用于获取闭包的上值在 Lua 栈中的索引。这个索引是一个伪索引,他和其他的栈索引一样,唯一的区别在于它不存在于栈中。

参数:

 

参数 i : 表示要获取的上值的索引,第一个上值的索引为 1 。

返回值:

 

返回值是一个整数,表示该上值在 Lua 栈中的索引。

 

如果传入的索引超出了范围,则会返回 LUA_TNONE 。可以使用 lua_isnone 函数进行判断上值的伪索引是否合法,例如下面代码:

image.png

三、共享上值

在封装一个库给 Lua 进行调用的时候,有时需要库函数间共享一些数值或变量。虽然注册表也可以达到这一目的,但不够优雅,毕竟将库的过多细节暴露,并且存在 key 被覆盖的风险,所以更好的做法应该是使用上值。

 

Lua 为这种场景提供了一种解决方案,简化在库函数间共享上值的做法。

 

之前我们创建一个 Lua 库时,一般都使用 luaL_newlib 函数,他其实是个宏,具体实现如下所示。

image.png

要达到共享上值的关键点在于 luaL_setfuncs 的三个参数,用 luaL_newlib 创建库,默认情况下传递的都是 0 ,即没有共享上值,所以我们只需要改造下就可以支持了。

定义一个库,这个库中有两个函数,共享三个上值,分别为整数型、字符串、table,两个函数均可对共享上值获取和修改

 

第一步,定义库函数和设置库的共享上值。

 

showInfo 和 showCode 是两个库函数,会获取各自的参数和共享上值,进行操作后返回给 Lua

 

共享上值的关键点在 luaopen_user 函数,函数中会压入三个值,然后调用 luaL_setfuncs 将这三个值作为库的共享上值。

image.png

image.png

image.png

第二步,编写 lua 文件。

只是简单的调用库函数,然后打印返回值。

image.png

第三步,将库函数添加到 Lua 中,并运行 Lua 文件。 image.png

运行结果如下。

image.png


四、注册表和上值的区别

注册表提供了全局变量的概念,只要获取到相同的 lua_State ,就能通过 lua_State 访问到相同的注册表,通过对应的 key 获取需要的 value 。

上值则实现了一种只能在特定的函数中可见的机制,相较于注册表能做到更小粒度的共享值。

五、写在最后

Lua 项目地址:Github传送门 (如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)

如果觉得本篇博文对你有所启发或是解决了困惑,点个赞或关注我呀

公众号搜索 “江澎涌”,更多优质文章会第一时间分享与你。

 

目录
相关文章
|
5月前
lua字符串与十六进制数据转换
lua字符串与十六进制数据转换
155 2
|
5月前
|
存储 C语言 图形学
C 函数中如何保存 Lua 的数据(1)
C 函数中如何保存 Lua 的数据(1)
77 0
|
11月前
|
存储 Java C语言
lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】
lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】
84 0
|
5月前
|
C语言
Lua 函数
Lua中的函数支持可变参数,以三点(...)表示。函数既可完成任务,也可用于计算并返回值。例如,`add(...)`函数接受任意数量参数并返回它们的和。要处理可变参数,可以将其赋值给一个表,如`arg={...}`。计算平均值的`average(...)`函数展示了如何遍历和使用这些参数。通过`select("#",...)`可以获取参数数量,`select(n, ...)`则用于访问特定位置的参数。函数定义如`function fwrite(fmt, ...)`允许固定参数与可变参数结合使用。
|
5月前
|
C语言
Lua 函数
Lua中的函数支持可变参数,用三点`...`表示。函数可以用于执行任务或返回计算值。示例中展示了如何处理可变参数,如计算参数总和(`add`函数)和平均值(`average`函数)。`select("#",...)`用于获取参数数量,`select(n, ...)`用于获取从n开始的参数列表。`average`函数在不同实例中展示了使用可变参数的方式,始终返回参数的平均值。`fwrite`函数展示了固定参数与可变参数的组合使用。
Lua 函数
Lua函数是主要的抽象机制,用于执行任务或计算值。函数定义格式包括可选的函数作用域(默认全局)、函数名、参数列表和函数体。例如,定义一个名为`max`的函数,接收两个参数`num1`和`num2`,返回它们中的最大值。函数可以作为参数传递,如示例中将`myprint`函数传递给`add`函数,实现功能组合。
|
11月前
|
消息中间件 存储 NoSQL
【实战】使用Lua脚本怎么清理redis中的数据【实战】使用Lua脚本怎么清理redis中的数据
首先我们通过hiredis 向redis 中写入了数据,这里我们主要以测试为目的,所以,Key 值设定为毫秒级时间戳。
106 0
[✔️]lua中的module函数
[✔️]lua中的module函数
167 0
|
4月前
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
206 0
下一篇
无影云桌面