[zz]为 lua 封装 C 对象的生存期管理问题
轉(zhuǎn)載自:http://blog.codingnow.com/2009/03/lua_c_wrapper.html
把 C 里的對象封裝到 lua 中,方便 lua 程序調(diào)用,是很常見的一項工作。
里面最大的問題是生命期管理問題。
通常有兩種方案:
第一:編寫 C 庫的時候,完全針對 lua 設計,所有對象都有 lua_newuserdata 分配內(nèi)存。對象和對象之間的聯(lián)系可以使用 userdata 的 環(huán)境表,把對象間的引用放在里面,使得 lua 的 gc 過程可以正常進行。
第二:給 C 對象簡單加一個殼。lua 的 userdata 中僅僅保存 C 對象指針。然后給 userdata 設置 gc 元方法,在被回收時,正確調(diào)用 C 對象的銷毀函數(shù)。
以上兩種方案都依賴 lua 的 full userdata ,這里,我想提供第三種方案,僅使用 lightuserdata 完成這項工作。
這第三方案未必比前兩種都好。雖然從字面上理解 light userdata 比 full userdata 更廉價,但誠如 pil 中所言,full userdata 也非過于重量。
最終的方案選擇還是要結(jié)合實際的設計,仔細考量。
方法很簡單:
如果你可以保證,所有對象用戶只從 lua 層面創(chuàng)建,并依賴 lua 層的 gc 機制銷毀。那么僅需要在 lua 中維護一張弱表,把每個創(chuàng)建出來的 lua 封裝對象(一般是一個 table)放在這張表中(其實是一個集合)。
同時,在 C 中也維護一個集合(一個簡單的對象指針數(shù)組即可)。每次對象創(chuàng)建,便把 C 對象指針放入集合。
這樣, C 里的集合引用的對象一定是 lua 中那個集合的超集。下面,僅需要周期性的對比兩個集合,把 C 集合中多余的對象銷毀掉即可。
真正使用時,尤其是前面提到的前提(所有對象只能從 lua 中管理)不滿足時,還需要考慮更多細節(jié),這里不再贅述了。
3 月 14 日 補充:
可以通過向 lua 的對象集合(一個弱表)中放置一個 C 收集器來實現(xiàn)在 lua gc 后自動回收 C 對象。這個 C 收集器實現(xiàn)簡單,用一個 userdata 綁定一個 gc 元方法即可。
需要注意的是,創(chuàng)建 C 對象和創(chuàng)建 lua 對象,并將兩者綁定需要是一個原子操作。否則中間可能被 gc 打斷,導致 C 對象被提前回收。
總結(jié)
以上是生活随笔為你收集整理的[zz]为 lua 封装 C 对象的生存期管理问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发---推荐16个国外的源码下载网站
- 下一篇: 如何禁止普通用户通过rsh登陆计算节点