[zz]lua綁定中(tolua++)需注意的事項

若是你暴露一個複雜對象給Lua,實現相似於OO編程的話,那麼也要把析構函數暴露給Lua.編程

不然的話,lua gc的時候,回收垃圾對象,沒有找到回收函數,就直接free掉了,這在C++中,是至關致命的.函數

 

tolua++中的tolua_cclass函數,用來註冊lua對象,lua

TOLUA_API void tolua_cclass (lua_State* L, const char * lname, const char * name, const char * base, lua_CFunction col)

 同時會把最後的那個參數col,註冊到lua對象的元表裏面:spa

static void push_collector(lua_State* L, const char * type, lua_CFunction col) {
 
     /* push collector function, but only if it's not NULL, or if there's no
        collector already */
     if (!col) return ;
     luaL_getmetatable(L,type);
     lua_pushstring(L, ".collector" );
         //....
     lua_pushcfunction(L,col);
         //....

 而發生gc的時候,class_gc_event函數會去在lua對象的元表裏面找".collector"這個key,若是沒找到,就用default的析構,不然就用用戶提供的析構函數:code

top = lua_gettop(L);
if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */
{
     /*fprintf(stderr, "Found type!\n");*/
     /* get gc function */
     lua_pushliteral(L, ".collector" );
     lua_rawget(L,-2);           /* stack: gc umt mt collector */
     if (lua_isfunction(L,-1)) {
         /*fprintf(stderr, "Found .collector!\n");*/
     }
     else {
         lua_pop(L,1);
         /*fprintf(stderr, "Using default cleanup\n");*/
         lua_pushcfunction(L,<strong>tolua_default_collect</strong>); //這個是默認的析構函數
     }
 
     lua_pushvalue(L,1);         /* stack: gc umt mt collector u */
     lua_call(L,1,0);

 而默認的析構函數是C free的簡單封裝:對象

TOLUA_API int tolua_default_collect (lua_State* tolua_S)
{
  void * self = tolua_tousertype(tolua_S,1,0);
  free (self);
  return 0;
}

 

若是你經過tolua++註冊一個複雜類型給lua的話,析構函數不被調用,而直接調用了free,會發生不少未定義行爲.blog

相關文章
相關標籤/搜索