今天同事在设计引擎的脚本接口时遇到一个问题:需要把 C 对象指针放到 Lua 中,允许 Lua 保存这个指针,并传递给其它模块。 这是给 Lua 写 C 扩展时常见的问题,撇开如何如何将对象的方法导入 Lua 这个更复杂的问题不谈,我主要想说说 C 对象的生命期管理的问题。 一开始的设计是把对象的销毁方法也导入 Lua ,由脚本程序员手工管理。这是很明显的 C 程序员的思路:谁构造谁释放。但在这里是不合适的,不符合带 gc 机制语言的习惯。 ... Click to expand...
成都创新互联公司是网站建设专家,致力于互联网品牌建设与网络营销,专业领域包括网站制作、成都网站设计、电商网站制作开发、微信小程序、微信营销、系统平台开发,与其他网站设计及系统开发公司不同,我们的整合解决方案结合了恒基网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,且不断评估并优化我们的方案,为客户提供全方位的互联网品牌整合方案!
今天同事在设计引擎的脚本接口时遇到一个问题:需要把 C 对象指针放到 Lua 中,允许 Lua 保存这个指针,并传递给其它模块。
这是给 Lua 写 C 扩展时常见的问题,撇开如何如何将对象的方法导入 Lua 这个更复杂的问题不谈,我主要想说说 C 对象的生命期管理的问题。
一开始的设计是把对象的销毁方法也导入 Lua ,由脚本程序员手工管理。这是很明显的 C 程序员的思路:谁构造谁释放。但在这里是不合适的,不符合带 gc 机制语言的习惯。
我们当然希望脚本更为健壮,不需要考虑对象释放的问题。所以晚上我想了一下,修改了一下这部分的实现。
从效率方面着手,这个问题分两种情况:
***种情况很简单,C 对象可以被传入 Lua 状态机后,逻辑上可以确保它的指针一定一直有效,程序直到 Lua 状态机本身关闭后,才会删除对象。这种情况我们只需要把 C 对象指针以 lightuserdata 的形式压入堆栈即可。
第二种情况就是,C 对象由脚本创建或获得。在没有地方对其引用之后,对象则应该被删除以释放其占用的资源。这种情况,我们应该使用 fulluserdata ,为其注册 gc 元方法。
不过问题复杂在,引用 C 对象的可以是脚本也可以在 C 代码中。脚本中对 userdata 的引用 lua 状态机会自行解决,但 lua 的 gc 过程并不能直接知道 C 中是否对对象还有引用,这就是我们需要做的工作了。
python 的 C 接口提供了相关的函数,可以在 C 界面上对 PyObject 加减引用。但是 lua 的 gc 是基于根扫描的,状态机中并没有引用计数。很自然的,lua 就没有类似的 C 接口了。
我的解决方法是,在 lua 注册表中创建一个弱表(value 是弱的,而 key 是强的),把 C 对象指针和对应的 fulluserdata 以及它在 C 中的引用数量记入这个表里。然后提供一对 API 对引用计数增减。当引用计数为 0 时,清除关于计数的表项。最终可利用 gc 回收掉已无引用的 C 对象。
详细的程序可以参考我的 wiki 上贴的代码。
这里补充几点说明:
所有对象的 gc 元方法是共享的,而不是每次创建 fulluserdata 创建一个新的元表。这是一个简单的优化,可以节省不少的内存。方便起见,这个元表也放在那个弱表内。注意:在 Lua 中,每次压入一个 CFucntion 都会重新分配内存创建一个新对象。所以应该尽可能的共用。
每次从 C 对象指针生成 fulluserdata 时,都会去检查以前是否生成过。这样才能使引用计数统一计算。
代码随手写的,并没有经过严格的测试,如果谁想拿去用可自便,但发现 bug 请通知我修改过来。
网站题目:在Lua中管理C对象
文章URL:http://www.mswzjz.cn/qtweb/news36/137736.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能