在C函數中儲存狀體:registry、reference和upvalues

來源:互聯網
上載者:User

標籤:style   blog   color   使用   os   strong   資料   問題   

  C函數可以通過堆棧來和Lua交換資料,但有時候C函數需要在函數體的範圍之外儲存某些Lua資料,那麼我們想到全域變數或static變數,這樣做的缺點是:(1)為Lua設計C函數庫時,導致不可重新進入;(2)不是所有的Lua值都能很好的儲存到C變數中。那麼可不可以將值儲存在Lua全域變數裡面呢,可以,Lua就提供了一個獨立的被稱為registry的表,但是Lua代碼本身不能訪問它。

1、registry全域註冊表
  解釋:一個普通的Lua表,使用假索引(pseudo-index)LUA_REGISTRYINDEX訪問。C代碼可以訪問,Lua代碼不能訪問。
  用途:解決C函數保留全域Lua值的問題。
  注意:所有的C程式庫共用相同的registry,所以對於key的命名需要具有全域唯一性。

    // 擷取registry表索引值"KEY"對應的值的方法:    lua_pushstring(L, "KEY");    lua_gettable(L, LUA_REGISTRYINDEX);

2、reference引用系統
  解釋:通過一個整數來唯一標識一個Lua資料對象,由兩個函數luaL_ref和luaL_unref組成,這對函數用來不需要擔心名稱衝突的將值儲存到registry中去。
  用途:將一個指向Lua值的reference儲存到一個C結構體中,這個reference是一個int的KEY。
  注意:棧頂值為nil的時候,不會產生reference,luaL_ref函數會返回LUA_REFNIL,而對LUA_REFNIL解引用是沒有效果的。
  重要函數:
  int luaL_ref (lua_State *L, int t);
  建立並返回一個引用reference,並將[reference,棧頂值v]加入t對應的表中。
  void luaL_unref (lua_State *L, int t, int ref);
  解引用,將t對應的表中的[reference,v]索引值對刪除。

    // 對棧頂的值v產生一個引用,即將[r, v]存到LUA_REGISTRYINDEX表中    int r = luaL_ref(L, LUA_REGISTRYINDEX);    // 將一個引用值入棧    lua_rawgeti(L, LUA_REGISTRYINDEX, r);    // 解引用,即釋放reference和值    luaL_unref(L, LUA_REGISTRYINDEX, r);

3、upvalues機制
  解釋:當建立一個C函數時可以關聯一些值,這樣就建立了一個C閉包,這些關聯值就叫做upvalues。
  用途:實現了與C static變數等價的概念,這種變數只能在特定的函數內可見。
  使用:通過lua_upvalueindex(n)產生假索引來訪問。

    // 預聲明    static int counter (lua_State *L);    // 建立C閉包的工廠函數    int newCounter (lua_State *L)    {        lua_pushnumber(L, 0);        lua_pushcclosure(L, &counter, 1);        return 1;    }    // C函數    static int counter (lua_State *L)    {        double val = lua_tonumber(L, lua_upvalueindex(1));        lua_pushnumber(L, ++val);   /* new value */        lua_pushvalue(L, -1);       /* duplicate it */        lua_replace(L, lua_upvalueindex(1));  /* update upvalue */        return 1;  /* return new value */    }

  注意:永遠不要使用數字作為registry 的key,因為這種類型的key是保留給reference系統使用。
  假索引(pseudo-index)的特點:(1)對應的值不在棧中;(2)使用方式類似於棧索引,大多數接受索引為參數的函數都能使用;(3)那些操作棧本身的函數不能使用假索引,比如lua_remove,lua_insert等。

  與Lua閉包(在Lua代碼中,一個閉包是一個從外部函數訪問局部變數的函數)不同的是,C閉包不能共用upvalues:每一個閉包都有自己獨立的變數集。然而,我們可以設定不同函數的upvalues指向同一個表,這樣這個表就變成了一個所有函數共用資料的地方。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.