zoukankan      html  css  js  c++  java
  • [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 对象被提前回收。

  • 相关阅读:
    Codeforces 992C(数学)
    Codeforces 990C (思维)
    Codeforces 989C (构造)
    POJ 1511 Invitation Cards(链式前向星,dij,反向建边)
    Codeforces 1335E2 Three Blocks Palindrome (hard version)(暴力)
    POJ 3273 Monthly Expense(二分)
    POJ 2566 Bound Found(尺取前缀和)
    POJ 1321 棋盘问题(dfs)
    HDU 1506 Largest Rectangle in a Histogram(单调栈)
    POJ 2823 Sliding Window(单调队列)
  • 原文地址:https://www.cnblogs.com/zhangzhang/p/2854832.html
Copyright © 2011-2022 走看看