mirror of https://github.com/axmolengine/axmol.git
278 lines
9.5 KiB
C++
278 lines
9.5 KiB
C++
/****************************************************************************
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
https://axis-project.github.io/
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "scripting/lua-bindings/manual/tolua_fix.h"
|
|
#include "base/CCRef.h"
|
|
#include "scripting/lua-bindings/manual/LuaBasicConversions.h"
|
|
#include <stdlib.h>
|
|
|
|
using namespace cocos2d;
|
|
|
|
static int s_function_ref_id = 0;
|
|
|
|
TOLUA_API void toluafix_open(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);
|
|
lua_newtable(L);
|
|
lua_rawset(L, LUA_REGISTRYINDEX);
|
|
|
|
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
|
|
lua_newtable(L);
|
|
lua_rawset(L, LUA_REGISTRYINDEX);
|
|
}
|
|
|
|
TOLUA_API int toluafix_pushusertype_ccobject(lua_State* L, int refid, int* p_refid, void* ptr, const char* type)
|
|
{
|
|
if (ptr == NULL || p_refid == NULL)
|
|
{
|
|
lua_pushnil(L);
|
|
return -1;
|
|
}
|
|
|
|
Ref* vPtr = static_cast<Ref*>(ptr);
|
|
const char* vType = getLuaTypeName(vPtr, type);
|
|
|
|
if (*p_refid == 0)
|
|
{
|
|
*p_refid = refid;
|
|
|
|
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */
|
|
lua_pushinteger(L, refid); /* stack: refid_ptr refid */
|
|
lua_pushlightuserdata(L, vPtr); /* stack: refid_ptr refid ptr */
|
|
|
|
lua_rawset(L, -3); /* refid_ptr[refid] = ptr, stack: refid_ptr */
|
|
lua_pop(L, 1); /* stack: - */
|
|
|
|
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_type */
|
|
lua_pushinteger(L, refid); /* stack: refid_type refid */
|
|
lua_pushstring(L, vType); /* stack: refid_type refid type */
|
|
lua_rawset(L, -3); /* refid_type[refid] = type, stack: refid_type */
|
|
lua_pop(L, 1); /* stack: - */
|
|
|
|
// printf("[LUA] push CCObject OK - refid: %d, ptr: %x, type: %s\n", *p_refid, (int)ptr, type);
|
|
}
|
|
|
|
tolua_pushusertype_and_addtoroot(L, vPtr, vType);
|
|
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int toluafix_remove_ccobject_by_refid(lua_State* L, int refid)
|
|
{
|
|
void* ptr = NULL;
|
|
const char* type = NULL;
|
|
void** ud = NULL;
|
|
if (refid == 0)
|
|
return -1;
|
|
|
|
// get ptr from tolua_refid_ptr_mapping
|
|
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */
|
|
lua_pushinteger(L, refid); /* stack: refid_ptr refid */
|
|
lua_rawget(L, -2); /* stack: refid_ptr ptr */
|
|
ptr = lua_touserdata(L, -1);
|
|
lua_pop(L, 1); /* stack: refid_ptr */
|
|
if (ptr == NULL)
|
|
{
|
|
lua_pop(L, 1);
|
|
// Lua stack has closed, C++ object not in Lua.
|
|
// printf("[LUA ERROR] remove CCObject with NULL ptr, refid: %d\n", refid);
|
|
return -2;
|
|
}
|
|
|
|
// 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);
|
|
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);
|
|
printf("[LUA ERROR] remove CCObject with NULL type, refid: %d, ptr: %p\n", refid, ptr);
|
|
return -1;
|
|
}
|
|
|
|
type = lua_tostring(L, -1);
|
|
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 */
|
|
};
|
|
|
|
// cleanup root
|
|
tolua_remove_value_from_root(L, ptr);
|
|
|
|
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.
|
|
// printf("[LUA ERROR] remove CCObject with NULL ubox, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
|
|
lua_pop(L, 3);
|
|
return -3;
|
|
}
|
|
|
|
// cleanup peertable
|
|
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
|
lua_setfenv(L, -2);
|
|
|
|
ud = (void**)lua_touserdata(L, -1);
|
|
lua_pop(L, 1); /* stack: mt ubox */
|
|
if (ud == NULL)
|
|
{
|
|
printf("[LUA ERROR] remove CCObject with NULL userdata, refid: %d, ptr: %p, type: %s\n", refid, ptr, type);
|
|
lua_pop(L, 2);
|
|
return -1;
|
|
}
|
|
|
|
// 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 */
|
|
|
|
lua_pop(L, 2);
|
|
// printf("[LUA] remove CCObject, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)
|
|
{
|
|
// function at lo
|
|
if (!lua_isfunction(L, lo))
|
|
return 0;
|
|
|
|
s_function_ref_id++;
|
|
|
|
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: fun ... refid_fun */
|
|
lua_pushinteger(L, s_function_ref_id); /* stack: fun ... refid_fun refid */
|
|
lua_pushvalue(L, lo); /* stack: fun ... refid_fun refid fun */
|
|
|
|
lua_rawset(L, -3); /* refid_fun[refid] = fun, stack: fun ... refid_ptr */
|
|
lua_pop(L, 1); /* stack: fun ... */
|
|
|
|
return s_function_ref_id;
|
|
|
|
// lua_pushvalue(L, lo); /* stack: ... func */
|
|
// return luaL_ref(L, LUA_REGISTRYINDEX);
|
|
}
|
|
|
|
TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid)
|
|
{
|
|
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: ... refid_fun */
|
|
lua_pushinteger(L, refid); /* stack: ... refid_fun refid */
|
|
lua_rawget(L, -2); /* stack: ... refid_fun fun */
|
|
lua_remove(L, -2); /* stack: ... fun */
|
|
}
|
|
|
|
TOLUA_API void toluafix_remove_function_by_refid(lua_State* L, int refid)
|
|
{
|
|
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: ... refid_fun */
|
|
lua_pushinteger(L, refid); /* stack: ... refid_fun refid */
|
|
lua_pushnil(L); /* stack: ... refid_fun refid nil */
|
|
lua_rawset(L, -3); /* refid_fun[refid] = fun, stack: ... refid_ptr */
|
|
lua_pop(L, 1); /* stack: ... */
|
|
|
|
// luaL_unref(L, LUA_REGISTRYINDEX, refid);
|
|
}
|
|
|
|
// check lua value is function
|
|
TOLUA_API int toluafix_isfunction(lua_State* L, int lo, const char* type, int def, 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;
|
|
}
|
|
|
|
TOLUA_API int toluafix_totable(lua_State* L, int lo, int def)
|
|
{
|
|
return lo;
|
|
}
|
|
|
|
TOLUA_API int toluafix_istable(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
|
|
{
|
|
return tolua_istable(L, lo, def, err);
|
|
}
|
|
|
|
TOLUA_API void toluafix_stack_dump(lua_State* L, const char* label)
|
|
{
|
|
int i;
|
|
int top = lua_gettop(L);
|
|
printf("Total [%d] in lua stack: %s\n", top, label != 0 ? label : "");
|
|
for (i = -1; i >= -top; i--)
|
|
{
|
|
int t = lua_type(L, i);
|
|
switch (t)
|
|
{
|
|
case LUA_TSTRING:
|
|
printf(" [%02d] string %s\n", i, lua_tostring(L, i));
|
|
break;
|
|
case LUA_TBOOLEAN:
|
|
printf(" [%02d] boolean %s\n", i, lua_toboolean(L, i) ? "true" : "false");
|
|
break;
|
|
case LUA_TNUMBER:
|
|
printf(" [%02d] number %g\n", i, lua_tonumber(L, i));
|
|
break;
|
|
default:
|
|
printf(" [%02d] %s\n", i, lua_typename(L, t));
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|