axmol/lua/cocos2dx_support/tolua_fix.c

216 lines
8.8 KiB
C
Raw Normal View History

2011-11-18 20:36:39 +08:00
#include "tolua_fix.h"
#include <stdlib.h>
2011-11-18 20:36:39 +08:00
TOLUA_API void tolua_prepare_ccobject_table(lua_State* L)
{
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
2011-11-18 20:36:39 +08:00
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING);
2011-11-18 20:36:39 +08:00
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
}
2012-01-08 21:03:16 +08:00
TOLUA_API int tolua_pushusertype_ccobject(lua_State* L,
int refid,
int* p_refid,
2012-01-08 21:03:16 +08:00
void* ptr,
const char* type)
2011-11-18 20:36:39 +08:00
{
if (ptr == NULL || p_refid == NULL)
{
lua_pushnil(L);
return -1;
}
2011-11-18 20:36:39 +08:00
if (*p_refid == 0)
{
*p_refid = refid;
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
2011-11-18 20:36:39 +08:00
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */
lua_pushinteger(L, refid); /* stack: refid_ptr refid */
lua_pushlightuserdata(L, ptr); /* stack: refid_ptr refid ptr */
2011-12-17 11:18:33 +08:00
2011-11-18 20:36:39 +08:00
lua_rawset(L, -3); /* refid_ptr[refid] = ptr, stack: refid_ptr */
lua_pop(L, 1); /* stack: - */
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
2011-11-18 20:36:39 +08:00
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_type */
lua_pushinteger(L, refid); /* stack: refid_type refid */
lua_pushstring(L, type); /* stack: refid_type refid type */
lua_rawset(L, -3); /* refid_type[refid] = type, stack: refid_type */
lua_pop(L, 1); /* stack: - */
2011-12-17 11:18:33 +08:00
//printf("[LUA] push CCObject OK - refid: %d, ptr: %x, type: %s\n", *p_refid, (int)ptr, type);
2011-11-18 20:36:39 +08:00
}
tolua_pushusertype(L, ptr, type);
return 0;
2011-11-18 20:36:39 +08:00
}
TOLUA_API int tolua_remove_ccobject_by_refid(lua_State* L, int refid)
2011-11-18 20:36:39 +08:00
{
2012-02-10 12:02:46 +08:00
void* ptr = NULL;
const char* type = NULL;
void** ud = NULL;
if (refid == 0) return -1;
2011-11-18 20:36:39 +08:00
// get ptr from tolua_refid_ptr_mapping
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
2011-11-18 20:36:39 +08:00
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */
lua_pushinteger(L, refid); /* stack: refid_ptr refid */
lua_rawget(L, -2); /* stack: refid_ptr ptr */
2012-02-10 12:02:46 +08:00
ptr = lua_touserdata(L, -1);
2011-11-18 20:36:39 +08:00
lua_pop(L, 1); /* stack: refid_ptr */
if (ptr == NULL)
{
lua_pop(L, 1);
2011-11-29 17:11:47 +08:00
// Lua stack has closed, C++ object not in Lua.
2012-01-08 21:03:16 +08:00
// printf("[LUA ERROR] remove CCObject with NULL ptr, refid: %d\n", refid);
return -2;
2011-11-18 20:36:39 +08:00
}
// remove ptr from tolua_refid_ptr_mapping
lua_pushinteger(L, refid); /* stack: refid_ptr refid */
lua_pushnil(L); /* stack: refid_ptr refid nil */
lua_rawset(L, -3); /* delete refid_ptr[refid], stack: refid_ptr */
lua_pop(L, 1); /* stack: - */
// get type from tolua_refid_type_mapping
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
2011-11-18 20:36:39 +08:00
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_type */
lua_pushinteger(L, refid); /* stack: refid_type refid */
lua_rawget(L, -2); /* stack: refid_type type */
if (lua_isnil(L, -1))
{
lua_pop(L, 2);
2011-11-29 17:11:47 +08:00
printf("[LUA ERROR] remove CCObject with NULL type, refid: %d, ptr: %x\n", refid, (int)ptr);
return -1;
2011-11-18 20:36:39 +08:00
}
2012-02-10 12:02:46 +08:00
type = lua_tostring(L, -1);
2011-11-18 20:36:39 +08:00
lua_pop(L, 1); /* stack: refid_type */
// remove type from tolua_refid_type_mapping
lua_pushinteger(L, refid); /* stack: refid_type refid */
lua_pushnil(L); /* stack: refid_type refid nil */
lua_rawset(L, -3); /* delete refid_type[refid], stack: refid_type */
lua_pop(L, 1); /* stack: - */
// get ubox
luaL_getmetatable(L, type); /* stack: mt */
lua_pushstring(L, "tolua_ubox"); /* stack: mt key */
lua_rawget(L, -2); /* stack: mt ubox */
if (lua_isnil(L, -1))
{
// use global ubox
lua_pop(L, 1); /* stack: mt */
lua_pushstring(L, "tolua_ubox"); /* stack: mt key */
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: mt ubox */
};
2011-11-18 20:36:39 +08:00
lua_pushlightuserdata(L, ptr); /* stack: mt ubox ptr */
lua_rawget(L,-2); /* stack: mt ubox ud */
if (lua_isnil(L, -1))
{
// Lua object has released (GC), C++ object not in ubox.
2012-01-08 21:03:16 +08:00
//printf("[LUA ERROR] remove CCObject with NULL ubox, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
2011-11-18 20:36:39 +08:00
lua_pop(L, 3);
return -3;
2011-11-18 20:36:39 +08:00
}
2012-02-10 12:02:46 +08:00
ud = (void**)lua_touserdata(L, -1);
2011-11-18 20:36:39 +08:00
lua_pop(L, 1); /* stack: mt ubox */
if (ud == NULL)
{
2011-11-29 17:11:47 +08:00
printf("[LUA ERROR] remove CCObject with NULL userdata, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
2011-11-18 20:36:39 +08:00
lua_pop(L, 2);
return -1;
2011-11-18 20:36:39 +08:00
}
// clean userdata
*ud = NULL;
lua_pushlightuserdata(L, ptr); /* stack: mt ubox ptr */
lua_pushnil(L); /* stack: mt ubox ptr nil */
lua_rawset(L, -3); /* ubox[ptr] = nil, stack: mt ubox */
2011-11-18 20:36:39 +08:00
lua_pop(L, 2);
2011-12-17 11:18:33 +08:00
//printf("[LUA] remove CCObject, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
return 0;
2011-11-18 20:36:39 +08:00
}
TOLUA_API int tolua_ref_function(lua_State* L, int lo, int def)
2011-11-18 20:36:39 +08:00
{
static int functionRefIDCount = 0;
if (lua_gettop(L) < abs(lo) || !lua_isfunction(L, lo)) return 0;
++functionRefIDCount;
/* stack: ... func ... */
lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: ... func ... refid_func */
lua_pushinteger(L, functionRefIDCount); /* stack: ... func ... refid_func refid */
lua_pushvalue(L, lo); /* stack: ... func ... refid_func refid func */
lua_rawset(L, -3); /* refid_func[refid] = func, stack: ... func ... refid_func */
lua_pop(L, 1); /* stack: ... func ... */
return functionRefIDCount;
2011-11-18 20:36:39 +08:00
}
TOLUA_API void tolua_remove_function_by_refid(lua_State* L, int refid)
{
lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_func */
lua_pushinteger(L, refid); /* stack: refid_func refid */
lua_pushnil(L); /* stack: refid_func refid nil */
2011-11-29 17:11:47 +08:00
lua_rawget(L, -2); /* delete refid_func[refid], stack: refid_func */
lua_pop(L, 1); /* stack: - */
}
2011-11-18 20:36:39 +08:00
// check lua value is funciton
2011-11-18 20:36:39 +08:00
TOLUA_API int tolua_isfunction(lua_State* L, int lo, tolua_Error* err)
{
if (lua_gettop(L) >= abs(lo) && lua_isfunction(L, lo))
{
return 1;
}
err->index = lo;
err->array = 0;
err->type = "[not function]";
return 0;
}
2011-12-08 00:30:46 +08:00
2011-12-17 11:18:33 +08:00
TOLUA_API void tolua_stack_dump(lua_State* L, const char* label)
2011-12-08 00:30:46 +08:00
{
int i;
int top = lua_gettop(L);
2011-12-17 11:18:33 +08:00
printf("Total [%d] in lua stack: %s\n", top, label != 0 ? label : "");
for (i = -1; i >= -top; i--)
2011-12-08 00:30:46 +08:00
{
int t = lua_type(L, i);
switch (t)
{
case LUA_TSTRING:
2011-12-17 11:18:33 +08:00
printf(" [%02d] string %s\n", i, lua_tostring(L, i));
2011-12-08 00:30:46 +08:00
break;
case LUA_TBOOLEAN:
2011-12-17 11:18:33 +08:00
printf(" [%02d] boolean %s\n", i, lua_toboolean(L, i) ? "true" : "false");
2011-12-08 00:30:46 +08:00
break;
case LUA_TNUMBER:
2011-12-17 11:18:33 +08:00
printf(" [%02d] number %g\n", i, lua_tonumber(L, i));
2011-12-08 00:30:46 +08:00
break;
default:
2011-12-17 11:18:33 +08:00
printf(" [%02d] %s\n", i, lua_typename(L, t));
2011-12-08 00:30:46 +08:00
}
}
2011-12-17 11:18:33 +08:00
printf("\n");
2011-12-08 00:30:46 +08:00
}