乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      為 Lua 綁定 C/C++ 對象 | 創(chuàng)業(yè)咖

       quasiceo 2014-01-15

      為 Lua 綁定 C/C++ 對象

       2013年01月10日 11:57  60人閱讀   搶沙發(fā)  標(biāo)簽:

      如何綁定 C/C++ 對象到 Lua 里?通常是創(chuàng)建一個(gè) userdata ,存放 C/C++ 對象指針,然后給 userdata 添加元表,用 index 元方法映射 C/C++ 中的對象方法。

      也有另一個(gè)手段,直接用 lightuserdata 保存 C/C++ 對象指針放到 Lua 中,在 Lua 中創(chuàng)建一個(gè) table 附加元表來來包裝這個(gè)指針,效果是類似的。區(qū)別在于對象生命期的管理方式有所不同。就這個(gè)問題,幾年前我寫過一篇 blog 。

      綁定 C/C++ 對象到 Lua 里的設(shè)計(jì)難點(diǎn)往往在這個(gè)正確的生命期管理上。因?yàn)?C/C++ 沒有 GC 系統(tǒng),依賴手工管理資源;而 Lua 則是利用 GC 做自動(dòng)回收。這兩者的差異容易導(dǎo)致在 Lua 中的對象對應(yīng)的 C/C++ 對象已經(jīng)銷毀而 Lua 層不自知,或 Lua 層中已無對象之引用,而 C/C++ 層中卻未能及時(shí)回收資源而造成內(nèi)存泄露。

      理清這個(gè)問題,首先你要確定,你打算以 Lua 為主干來維護(hù)對象的生命期,還是以 C/C++ 層為主干 Lua 部分只是做一些對這些對象的行為控制。

      我個(gè)人主張圍繞 Lua 來開發(fā),C/C++ 只是寫一些性能相關(guān)的庫供 Lua 調(diào)用,即框架層在 Lua 中。這樣,C/C++ 層只提供對象的創(chuàng)建和銷毀函數(shù),不要用 C 指針做對象的相互引用。Lua 中對象被回收時(shí),銷毀對應(yīng)的 C 對象即可。

      但是,也有相當(dāng)多的項(xiàng)目做不到這點(diǎn)。Lua 是在后期引入的,之前 C/C++ 框架層中已做好了相當(dāng)之復(fù)雜的對象管理?;蛘邩?gòu)架師不希望把腳本層過多的侵入引擎的設(shè)計(jì)。

      那么,下面給出另一個(gè)方案。

      我們將包裝進(jìn) Lua 的 C 對象稱為 script object ,那么只需要提供三個(gè)函數(shù)即可。

      int
      script_pushobject(lua_State *L, void * object) {
          void **ud;
          if (luaL_newmetatable(L, "script")) {
              // 在注冊表中創(chuàng)建一個(gè)表存放所有的 object 指針到 userdata 的關(guān)系。
              // 這個(gè)表應(yīng)該是一個(gè) weak table ,當(dāng) Lua 中不再存在對 C 對象的引用會(huì)刪除對應(yīng)的記錄。
              lua_newtable(L);
              lua_pushliteral(L, "kv");
              lua_setfield(L, -2, "__mode");
              lua_setmetatable(L, -2);
          }
          lua_rawgetp(L,-1,object);
          if (lua_type(L,-1)==LUA_TUSERDATA) {
              ud = (void **)lua_touserdata(L,-1);
              if (*ud == object) {
                  lua_replace(L, -2);
                  return 0;
              }
              // C 對象指針被釋放后,有可能地址被重用。
              // 這個(gè)時(shí)候,可能取到曾經(jīng)保存起來的 userdata ,里面的指針必然為空。
              assert(*ud == NULL);
          }
          ud = (void **)lua_newuserdata(L, sizeof(void*));
          *ud = object;
          lua_pushvalue(L, -1);
          lua_rawsetp(L, -4, object);
          lua_replace(L, -3);
          lua_pop(L,1);
          return 1;
      }
      

      這個(gè)函數(shù)把一個(gè) C 對象指針置入對應(yīng)的 userdata ,如果是第一次 push 則創(chuàng)建出新的 userdata ,否則復(fù)用曾經(jīng)創(chuàng)建過的。

      void *
      script_toobject(lua_State *L, int index) {
          void **ud = (void **)lua_touserdata(L,index);
          if (ud == NULL)
              return NULL;
          // 如果 object 已在 C 代碼中銷毀,*ud 為 NULL 。
          return *ud;
      }
      

      這個(gè)函數(shù)把 index 處的 userdata 轉(zhuǎn)換為一個(gè) C 對象。如果對象已經(jīng)銷毀,則返回 NULL 指針。 在給這個(gè)對象綁定 C 方法時(shí),應(yīng)注意在 toobject 調(diào)用后,全部對指針做檢查,空指針應(yīng)該被正確處理。

      void
      script_deleteobject(lua_State *L, void *object) {
          luaL_getmetatable(L, "script");
          if (lua_istable(L,-1)) {
              lua_rawgetp(L, -1, object);
              if (lua_type(L,-1) == LUA_TUSERDATA) {
                  void **ud = (void **)lua_touserdata(L,-1);
                  // 這個(gè) assert 防止 deleteobject 被重復(fù)調(diào)用。
                  assert(*ud == object);
                  // 銷毀一個(gè)被 Lua 引用住的對象,只需要把 *ud 置為 NULL 。
                  *ud = NULL;
              }
              lua_pop(L,2);
          } else {
              // 有可能從未調(diào)用過 pushobject ,此時(shí)注冊表中 script 項(xiàng)尚未建立。
              lua_pop(L,1);
          }
      }
      

      這個(gè)函數(shù)會(huì)解除 C 對象在 Lua 中的引用,后續(xù)在 Lua 中對這個(gè)對象的訪問,都將得到 NULL 指針。


      這些代碼是在我寫這篇 blog 的同時(shí)隨手寫的,并未經(jīng)過嚴(yán)格測試。它們也有許多改進(jìn)空間,比如給 C 對象加入類型,對 userdata 做更嚴(yán)格的檢查,等等。

      本文鏈接: 為 Lua 綁定 C/C++ 對象 | 創(chuàng)業(yè)咖

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多