若是你暴露一個複雜對象給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