在Lua中管理C对象

开发 前端
今天同事在设计引擎的脚本接口时遇到一个问题:需要把 C 对象指针放到 Lua 中,允许 Lua 保存这个指针,并传递给其它模块。

今天同事在设计引擎的脚本接口时遇到一个问题:需要把 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 请通知我修改过来。

原文链接:http://tech.it168.com/j/2008-02-17/200802171052983.shtml

责任编辑:陈四芳 来源: 来自ITPUB论坛
相关推荐

2011-08-22 17:13:00

LuaC++函数

2011-08-24 13:56:12

Lua游戏

2011-08-29 09:54:45

LUAJAVA 方法

2011-08-23 16:59:16

C++LUA脚本LUA API

2011-08-25 15:35:18

Lua游戏对象

2021-06-03 10:00:47

JavaScript 前端数克隆对象

2011-08-31 17:58:00

VS.netLUA开发环境

2013-12-13 16:53:00

Lua脚本语言C++

2011-08-24 13:27:07

Lua 游戏C接口脚本

2009-08-03 11:32:49

C#调用COM对象

2013-12-12 16:37:12

Lua脚本语言

2015-06-10 10:04:09

反向代理服务钓鱼

2022-04-29 07:35:49

SpringMVC构造函数

2013-12-13 17:21:14

Lua脚本语言

2013-12-13 16:46:18

Lua脚本语言

2011-08-23 17:11:13

Lua事件C#

2010-01-27 14:00:50

CC++运行环境

2011-08-23 09:50:29

LuaPlusLua 脚本

2009-07-01 09:17:36

对象比较Java

2009-05-08 09:46:37

微软C#集合对象
点赞
收藏

51CTO技术栈公众号