c/c++语言开发共享使用C API的弱表和GC终结器

我试图通过使用C API将其存储在弱表中来为函数值创建GC终结器。

我开始在纯Lua 5.2中编写原型:

local function myfinalizer() print 'Called finalizer' end function myfunc() print 'Called myfunc' end local sentinels = setmetatable({}, { __mode='k' }) sentinels[myfunc] = setmetatable({}, { __gc=myfinalizer }) myfunc() myfunc = nil collectgarbage 'collect' print 'Closing Lua' 

结果输出:

 Called myfunc Called finalizer Closing Lua 

原型似乎按预期工作。 以下是C版:

 #include  #include  #include "lua.h" #include "lualib.h" #include "lauxlib.h" static int my_finalizer(lua_State *L) { puts("Called finalizer"); return 0; } static int my_func(lua_State *L) { puts("Called myfunc"); return 0; } int main(void) { lua_State *L = luaL_newstate(); luaL_openlibs(L); // create sentinels table (weak keys) in registry lua_newtable(L); // t lua_newtable(L); // t mt lua_pushstring(L, "k"); // t mt v lua_setfield(L, -2, "__mode"); // t mt lua_setmetatable(L, -2); // t lua_setfield(L, LUA_REGISTRYINDEX, "sentinels"); // // push global function and register as sentinel lua_pushcfunction(L, my_func); // f lua_getfield(L, LUA_REGISTRYINDEX, "sentinels"); // ft lua_pushvalue(L, 1); // ftk lua_newuserdata(L, 0); // ftkv lua_newtable(L); // ftkv mt lua_pushcfunction(L, my_finalizer); // ftkv mt v lua_setfield(L, -2, "__gc"); // ftkv mt lua_setmetatable(L, -2); // ftkv lua_settable(L, -3); // ft lua_pop(L, 1); // f lua_setglobal(L, "myfunc"); // // execute test script and exit if (luaL_dostring(L, "myfunc(); myfunc=nil; collectgarbage'collect'")) { printf("Error: %sn", lua_tostring(L, -1)); } lua_gc(L, LUA_GCCOLLECT, 0); // suggestion: two full gc cycles fflush(stdout); // suggestion: immediate flush puts("Closing Lua"); lua_close(L); fflush(stdout); return EXIT_SUCCESS; } 

编译使用:

 $ gcc -std=c99 -Wall -Werror -pedantic -O2 -o main main.c -ldl -llua52 -lm 

结果输出:

 Called myfunc Closing Lua Called finalizer 

C版本有一些细微差别:

我很困惑为什么在C版本中myfunc终结器在运行完整的收集周期后没有执行。 我究竟做错了什么?

    正如Lua手册所述 :

    仅从弱表中删除具有显式构造的对象。 诸如数字和轻C函数之类的值不受垃圾收集的影响,因此不会从弱表中删除(除非收集其关联值)。

    你的my_func被推送没有任何upvalues,因此它是一个轻量级的C函数,并且在垃圾收集期间不会从弱表中删除它,因此关闭用户数据在关闭Lua状态之前不会变成垃圾。 如果您使用Lua函数而不是my_func ,或者如果您使用upvalues推送my_func(并且如果您修复了lua_gc调用中参数的顺序,那么您的代码应该有效)。

    总而言之, 不会从弱表中删除以下值类型(假设它们的相关键/值也未被删除):

    因此,你的程序应该可以正常使用Lua 5.1,因为没有简单的C函数(你仍然需要修复lua_gc调用)。

      以上就是c/c++开发分享使用C API的弱表和GC终结器相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/562786.html

      (0)
      上一篇 2021年2月5日
      下一篇 2021年2月5日

      精彩推荐