• [zz]为 lua 封装 C 对象的生存期管理问题


    转载自:http://blog.codingnow.com/2009/03/lua_c_wrapper.html

    把 C 里的对象封装到 lua 中,方便 lua 程序调用,是很常见的一项工作。

    里面最大的问题是生命期管理问题。

    通常有两种方案:

    第一:编写 C 库的时候,完全针对 lua 设计,所有对象都有 lua_newuserdata 分配内存。对象和对象之间的联系可以使用 userdata 的 环境表,把对象间的引用放在里面,使得 lua 的 gc 过程可以正常进行。

    第二:给 C 对象简单加一个壳。lua 的 userdata 中仅仅保存 C 对象指针。然后给 userdata 设置 gc 元方法,在被回收时,正确调用 C 对象的销毁函数。

    以上两种方案都依赖 lua 的 full userdata ,这里,我想提供第三种方案,仅使用 lightuserdata 完成这项工作。

    这第三方案未必比前两种都好。虽然从字面上理解 light userdata 比 full userdata 更廉价,但诚如 pil 中所言,full userdata 也非过于重量。

    最终的方案选择还是要结合实际的设计,仔细考量。

    方法很简单:

    如果你可以保证,所有对象用户只从 lua 层面创建,并依赖 lua 层的 gc 机制销毁。那么仅需要在 lua 中维护一张弱表,把每个创建出来的 lua 封装对象(一般是一个 table)放在这张表中(其实是一个集合)。

    同时,在 C 中也维护一个集合(一个简单的对象指针数组即可)。每次对象创建,便把 C 对象指针放入集合。

    这样, C 里的集合引用的对象一定是 lua 中那个集合的超集。下面,仅需要周期性的对比两个集合,把 C 集合中多余的对象销毁掉即可。

    真正使用时,尤其是前面提到的前提(所有对象只能从 lua 中管理)不满足时,还需要考虑更多细节,这里不再赘述了。


    3 月 14 日 补充:

    可以通过向 lua 的对象集合(一个弱表)中放置一个 C 收集器来实现在 lua gc 后自动回收 C 对象。这个 C 收集器实现简单,用一个 userdata 绑定一个 gc 元方法即可。

    需要注意的是,创建 C 对象和创建 lua 对象,并将两者绑定需要是一个原子操作。否则中间可能被 gc 打断,导致 C 对象被提前回收。

  • 相关阅读:
    字典树略解
    NOIP2018普及组初赛解题报告
    Codeforces 23A You're Given a String...
    远程消息推送的简单方法
    IOS5,6,7的新特性
    面试问题1
    IOS推送消息的步骤
    C面试问题
    label的自适应文本,让文本自适应
    TCP连接的三次握手,TCP/UDP区别联系,socket连接和http连接的区别
  • 原文地址:https://www.cnblogs.com/zhangzhang/p/2854832.html
Copyright © 2020-2023  润新知