Merge pull request #756 from dualface/fix-lua-engine-bugs

fixed #1030: Improve Lua engine
This commit is contained in:
minggo 2012-03-07 21:42:35 -08:00
commit 7dfe4224e1
5 changed files with 128 additions and 108 deletions

View File

@ -125,7 +125,7 @@ public:
virtual void removeCCObjectByID(int nLuaID) = 0;
/**
@brief Remove Lua function reference
@brief Remove Lua function handler
*/
virtual void removeLuaHandler(int nHandler) = 0;
@ -158,15 +158,20 @@ public:
virtual int executeGlobalFunction(const char* functionName) = 0;
/**
@brief Execute a function by ref id
@param The function ref id
@brief Execute a function by handler
@param The function handler
@param Number of parameters
@return The integer value returned from the script function.
*/
virtual int executeFunctionByRefID(int nHandler, int numArgs = 0) = 0;
virtual int executeFunctionByHandler(int nHandler, int numArgs = 0) = 0;
virtual int executeFunctionWithIntegerData(int nHandler, int data) = 0;
virtual int executeFunctionWithFloatData(int nHandler, float data) = 0;
virtual int executeFunctionWithBooleanData(int nHandler, bool data) = 0;
virtual int executeFunctionWithCCObject(int nHandler, CCObject* pObject, const char* typeName) = 0;
virtual int pushIntegerToLuaStack(int data) = 0;
virtual int pushFloatToLuaStack(int data) = 0;
virtual int pushBooleanToLuaStack(int data) = 0;
virtual int pushCCObjectToLuaStack(CCObject* pObject, const char* typeName) = 0;
// functions for excute touch event
virtual int executeTouchEvent(int nHandler, int eventType, CCTouch *pTouch) = 0;

View File

@ -24,11 +24,11 @@
#include "CCLuaEngine.h"
#include "tolua++.h"
#include "tolua_fix.h"
extern "C" {
#include "lualib.h"
#include "lauxlib.h"
#include "tolua_fix.h"
}
#include "cocos2d.h"
@ -148,88 +148,105 @@ int CCLuaEngine::executeGlobalFunction(const char* functionName)
return ret;
}
int CCLuaEngine::executeFunctionByRefID(int nHandler, int numArgs)
int CCLuaEngine::executeFunctionByHandler(int nHandler, int numArgs)
{
lua_pushstring(m_state, TOLUA_REFID_FUNC_MAPPING);
lua_rawget(m_state, LUA_REGISTRYINDEX); /* stack: ... refid_func */
lua_pushinteger(m_state, nHandler); /* stack: ... refid_func refid */
lua_rawget(m_state, -2); /* stack: ... refid_func func */
if (!lua_isfunction(m_state, -1))
if (pushFunctionByHandler(nHandler))
{
CCLOG("[LUA ERROR] function refid '%d' does not reference a Lua function", nHandler);
lua_pop(m_state, 2 + numArgs);
return 0;
}
if (numArgs > 0)
{
// [a1] [a2] refid_func func
// -4 -3 -2 -1
// [a1] [a2] refid_func func [a1]
// -5 -4 -3 -2 -1
int lo = -2 - numArgs;
for (int i = 0; i < numArgs; i++)
if (numArgs > 0)
{
tolua_pushvalue(m_state, lo); /* stack: ... refid_func func (...) */
lua_insert(m_state, -(numArgs + 1)); /* stack: ... func arg1 arg2 ... */
}
}
int error = 0;
try
{
error = lua_pcall(m_state, numArgs, 1, 0); /* stack: ... refid_func ret */
int error = 0;
// try
// {
error = lua_pcall(m_state, numArgs, 1, 0); /* stack: ... ret */
// }
// catch (exception& e)
// {
// CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ exception: %s", nHandler, e.what());
// lua_settop(m_state, 0);
// return 0;
// }
// catch (...)
// {
// CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ unknown exception.", nHandler);
// lua_settop(m_state, 0);
// return 0;
// }
if (error)
{
CCLOG("[LUA ERROR] %s", lua_tostring(m_state, - 1));
lua_settop(m_state, 0);
return 0;
}
// get return value
int ret = 0;
if (lua_isnumber(m_state, -1))
{
ret = lua_tointeger(m_state, -1);
}
else if (lua_isboolean(m_state, -1))
{
ret = lua_toboolean(m_state, -1);
}
lua_pop(m_state, 1);
return ret;
}
catch (exception& e)
else
{
CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ exception: %s", nHandler, e.what());
lua_settop(m_state, 0);
return 0;
}
catch (...)
{
CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ unknown exception.", nHandler);
lua_settop(m_state, 0);
return 0;
}
if (error)
{
CCLOG("[LUA ERROR] %s", lua_tostring(m_state, - 1));
lua_pop(m_state, 2 + numArgs); // clean error message
return 0;
}
// get return value
int ret = 0;
if (lua_isnumber(m_state, -1))
{
ret = lua_tointeger(m_state, -1);
}
else if (lua_isboolean(m_state, -1))
{
ret = lua_toboolean(m_state, -1);
}
lua_pop(m_state, 2 + numArgs);
return ret;
}
int CCLuaEngine::executeFunctionWithIntegerData(int nHandler, int data)
{
lua_pushinteger(m_state, data);
return executeFunctionByRefID(nHandler, 1);
return executeFunctionByHandler(nHandler, 1);
}
int CCLuaEngine::executeFunctionWithFloatData(int nHandler, float data)
{
lua_pushnumber(m_state, data);
return executeFunctionByRefID(nHandler, 1);
return executeFunctionByHandler(nHandler, 1);
}
int CCLuaEngine::executeFunctionWithBooleanData(int nHandler, bool data)
{
lua_pushboolean(m_state, data);
return executeFunctionByRefID(nHandler, 1);
return executeFunctionByHandler(nHandler, 1);
}
int CCLuaEngine::executeFunctionWithCCObject(int nHandler, CCObject* pObject, const char* typeName)
{
tolua_pushusertype_ccobject(m_state, pObject->m_uID, &pObject->m_nLuaID, pObject, typeName);
return executeFunctionByHandler(nHandler, 1);
}
int CCLuaEngine::pushIntegerToLuaStack(int data)
{
lua_pushinteger(m_state, data);
return lua_gettop(m_state);
}
int CCLuaEngine::pushFloatToLuaStack(int data)
{
lua_pushnumber(m_state, data);
return lua_gettop(m_state);
}
int CCLuaEngine::pushBooleanToLuaStack(int data)
{
lua_pushboolean(m_state, data);
return lua_gettop(m_state);
}
int CCLuaEngine::pushCCObjectToLuaStack(CCObject* pObject, const char* typeName)
{
tolua_pushusertype_ccobject(m_state, pObject->m_uID, &pObject->m_nLuaID, pObject, typeName);
return lua_gettop(m_state);
}
// functions for excute touch event
@ -239,7 +256,7 @@ int CCLuaEngine::executeTouchEvent(int nHandler, int eventType, CCTouch *pTouch)
lua_pushinteger(m_state, eventType);
lua_pushnumber(m_state, pt.x);
lua_pushnumber(m_state, pt.y);
return executeFunctionByRefID(nHandler, 3);
return executeFunctionByHandler(nHandler, 3);
}
int CCLuaEngine::executeTouchesEvent(int nHandler, int eventType, CCSet *pTouches)
@ -262,7 +279,7 @@ int CCLuaEngine::executeTouchesEvent(int nHandler, int eventType, CCSet *pTouche
++it;
}
return executeFunctionByRefID(nHandler, 2);
return executeFunctionByHandler(nHandler, 2);
}
int CCLuaEngine::executeSchedule(int nHandler, ccTime dt)
@ -295,4 +312,16 @@ void CCLuaEngine::addLuaLoader(lua_CFunction func)
lua_pop(m_state, 1);
}
bool CCLuaEngine::pushFunctionByHandler(int nHandler)
{
lua_rawgeti(m_state, LUA_REGISTRYINDEX, nHandler); /* stack: ... func */
if (!lua_isfunction(m_state, -1))
{
CCLOG("[LUA ERROR] function refid '%d' does not reference a Lua function", nHandler);
lua_pop(m_state, 1);
return false;
}
return true;
}
NS_CC_END

View File

@ -97,10 +97,15 @@ public:
@param Number of parameters
@return The integer value returned from the script function.
*/
virtual int executeFunctionByRefID(int nHandler, int numArgs = 0);
virtual int executeFunctionByHandler(int nHandler, int numArgs = 0);
virtual int executeFunctionWithIntegerData(int nHandler, int data);
virtual int executeFunctionWithFloatData(int nHandler, float data);
virtual int executeFunctionWithBooleanData(int nHandler, bool data);
virtual int executeFunctionWithCCObject(int nHandler, CCObject* pObject, const char* typeName);
virtual int pushIntegerToLuaStack(int data);
virtual int pushFloatToLuaStack(int data);
virtual int pushBooleanToLuaStack(int data);
virtual int pushCCObjectToLuaStack(CCObject* pObject, const char* typeName);
// functions for excute touch event
virtual int executeTouchEvent(int nHandler, int eventType, cocos2d::CCTouch *pTouch);
@ -121,6 +126,7 @@ private:
}
bool init(void);
bool pushFunctionByHandler(int nHandler);
lua_State* m_state;
};

View File

@ -11,10 +11,6 @@ TOLUA_API void tolua_prepare_ccobject_table(lua_State* L)
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING);
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
}
TOLUA_API int tolua_pushusertype_ccobject(lua_State* L,
@ -150,29 +146,14 @@ TOLUA_API int tolua_remove_ccobject_by_refid(lua_State* L, int refid)
TOLUA_API int tolua_ref_function(lua_State* L, int lo, int def)
{
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;
if (!lua_isfunction(L, lo)) return 0;
lua_pushvalue(L, lo); /* stack: ... func */
return luaL_ref(L, LUA_REGISTRYINDEX);
}
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 */
lua_rawget(L, -2); /* delete refid_func[refid], stack: refid_func */
lua_pop(L, 1); /* stack: - */
luaL_unref(L, LUA_REGISTRYINDEX, refid);
}
// check lua value is funciton

View File

@ -11,7 +11,6 @@ extern "C"
#define TOLUA_REFID_PTR_MAPPING "tolua_refid_ptr_mapping"
#define TOLUA_REFID_TYPE_MAPPING "tolua_refid_type_mapping"
#define TOLUA_REFID_FUNC_MAPPING "tolua_refid_func_mapping"
TOLUA_API void tolua_prepare_ccobject_table(lua_State* L);
TOLUA_API int tolua_pushusertype_ccobject(lua_State* L,