[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 對象被提前回收。
總結
以上是生活随笔為你收集整理的[zz]为 lua 封装 C 对象的生存期管理问题的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 开发---推荐16个国外的源码下载网站
- 下一篇: 如何禁止普通用户通过rsh登陆计算节点
