CCLuaStack.h详解
来源:互联网 发布:tower windows 破解版 编辑:程序博客网 时间:2024/05/16 05:49
这里贴上头文件说明以及实现
#ifndef __CC_LUA_STACK_H_#define __CC_LUA_STACK_H_extern "C" {#include "lua.h"}#include "cocos2d.h"#include "CCLuaValue.h"#define LUASTACK_USED_FOR_QUICK_COCOS2DXNS_CC_BEGINclass LuaStack : public Ref{public: static LuaStack *create(void); static LuaStack *attach(lua_State *L); virtual ~LuaStack(); /** @brief Method used to get a pointer to the lua_State that the script module is attached to. @return A pointer to the lua_State that the script module is attached to. */ //返回lua栈的指针 lua_State* getLuaState(void) { return _state; } /** @brief Add a path to find lua files in @param path to be added to the Lua path */ //增加搜索路径 virtual void addSearchPath(const char* path); /** @brief Add lua loader, now it is used on android */ // 添加Lua加载器。 // 参数 // func 指向加载器的函数指针。 virtual void addLuaLoader(lua_CFunction func); /** @brief reload script code contained in the given string. @param moduleFileName String object holding the filename of the script file that is to be executed @return 0 if the string is excuted correctly. @return other if the string is excuted wrongly. */ //重新加载给定字符串中包含的脚本代码。 //参数是要执行的脚本文件 //如果脚本文件被正确执行返回0。如果错误执行则返回其他数值 //重新加载对应moduleFileName指向的脚本文件。 如果package["loaded"][moduleFileName]值不为nil,它将先设置值为nil,然后,调用executeString函数。 virtual int reload(const char* moduleFileName); /** @brief Remove Object from lua state @param object The object to be removed. */ //通过操作相关Lua table,移除Ref对象在Lua table中的引用。 //同时,设置相应的userdata为nullptr以及移除去该对象相关的Lua函数的引用。 //目前的机制下,开发者不调用这个函数,这个函数将会在LuaEngier的析构函数中自动被调用。 virtual void removeScriptObjectByObject(Ref* object); /** @brief Remove Lua function reference */ //通过设置toluafix_refid_function_mapping[nHandle]=nil,移除Lua函数引用。 virtual void removeScriptHandler(int nHandler); /** @brief Remove Lua function reference */ //重新分配Lua函数的引用id。 virtual int reallocateScriptHandler(int nHandler); /** @brief Execute script code contained in the given string. @param codes holding the valid script code that should be executed. @return 0 if the string is excuted correctly. @return other if the string is excuted wrongly. */ //执行给定字符串中包含的脚本代码。 //codes 需被执行的脚本代码字符串。 //执行成功返回0,否则返回其它值。 virtual int executeString(const char* codes); /** @brief Execute a script file. @param filename String object holding the filename of the script file that is to be executed */ // 执行一个脚本文件。 // 参数 // filename 脚本文件的文件名。 // 返回 // 如果碰到错误或者执行结果没有返回值返回0,否则返回1。 virtual int executeScriptFile(const char* filename); /** @brief Execute a scripted global function. @brief The function should not take any parameters and should return an integer. @param functionName String object holding the name of the function, in the global script environment, that is to be executed. @return The integer value returned from the script function. */ // 执行全局的脚本函数。 该全局函数不应该有任何参数,同时返回一个整数。 // 参数 // functionName 全局脚本函数的字符串名称。 // 返回 // 从脚本函数返回的整数值。 virtual int executeGlobalFunction(const char* functionName); virtual void clean(void);//清空栈 virtual void pushInt(int intValue);//压入整数 virtual void pushFloat(float floatValue);//压入浮点数 virtual void pushLong(long longValue); virtual void pushBoolean(bool boolValue); virtual void pushString(const char* stringValue);//将一个以'\0'结束的字符串指针压入Lua栈。 virtual void pushString(const char* stringValue, int length);//调用lua_pushlstring压入长度为len的字符串 virtual void pushNil(void);//压入nil virtual void pushObject(Ref* objectValue, const char* typeName);//将一个Ref对象压入到Lua栈,详细信息请查阅toluafix_pushusertype_ccobject virtual void pushLuaValue(const LuaValue& value);//根据不同类型的LuaValue,它将会在函数内部调用其它相关的push函数 virtual void pushLuaValueDict(const LuaValueDict& dict);//将一个Lua table压入Lua栈。 这个Lua table的key值为字符串,value值依赖LuaValue的类型通过调用pushLuaValue获得, virtual void pushLuaValueArray(const LuaValueArray& array);//将一个Lua数组table压入Lua栈。 数组table的索引从1开始。 这个Lua数组table中的值通过调用pushLuaValue获得, virtual bool pushFunctionByHandler(int nHandler);//通过给定的nHandler查找toluafix_refid_function_mapping table获取对应的Lua函数指针,并将它压入Lua栈。 //如果无法找到nHanlder对应的Lua函数指针, 它会把压入一个nil值到栈顶,并且在在调试模式,它还会输出错误日志。 virtual int executeFunction(int numArgs);//通过numArgs值,获取Lua栈上-(numArgs + 1)索引处的Lua函数并执行 virtual int executeFunctionByHandler(int nHandler, int numArgs);//查找并执行nHandler对应的Lua函数,这个函数有numArgs个参数。 virtual int executeFunctionReturnArray(int handler,int numArgs,int numResults,__Array& resultArray);//查找并执行handler对应的Lua函数,这个函数有numArgs个参数。 //调用这个函数将会返回numResults个返回值(可能大于1)。 所有的返回值将存在resultArray中。 virtual int executeFunction(int handler, int numArgs, int numResults, const std::function<void(lua_State*,int)>& func);//查找并执行handler对应的Lua函数,这个函数有numArgs个参数。 //调用这个函数将会返回numResults个返回值(可能大于1)。 所有的返回值将被用在回调函数func中。 // 处理assert信息。 // 参数 // msg assert信息字符串。 // 返回 // 如果当前_callFromLua不为0返回true,否则返回false。virtual bool handleAssert(const char *msg, const char *cond, const char *file, int line); //设置的xxtea加密算法的key和sign。 // 参数 // key key字符串指针 // sign sign字符串指针 virtual void setXXTEAKeyAndSign(const char *key, const char *sign); virtual void cleanupXXTEAKeyAndSign(); virtual const char *getXXTEAKey(int *len); virtual const char *getXXTEASign(int *len); // 加载一个Lua程序块。该函数使用lua_load通过一个指向程序块的指针加载一块大小为chunkSize的Lua程序块。 如果当前支持xxtea算法,并且chunk的头部有sing签名,那么加载的程序块还需要进行解密操作。 // 参数 // L 当前lua_State。 // chunk 程序块指针。 // chunkSize 程序块大小。 // chunkName 程序块的名称。 // 返回 // 0,LUA_ERRSYNTAX或LUA_ERRMEM:。 int luaLoadBuffer(lua_State *L, const char *chunk, int chunkSize, const char *chunkName); //从zip文件加载Lua程序块 // 参数 // zipFilePath zip文件的文件路径。 // 返回 // 加载成功返回1,否则返回0。 int loadChunksFromZIP(const char *zipFilePath); //从当前的lua_State中加载Lua程序块。 // 参数 // L 当前的lua_State。 // 返回 // 加载成功返回1,否则返回0。 int luaLoadChunksFromZIP(lua_State *L); protected: LuaStack(void) : _state(nullptr) , _callFromLua(0) , _xxteaEnabled(false) , _xxteaKey(nullptr) , _xxteaKeyLen(0) , _xxteaSign(nullptr) , _xxteaSignLen(0) { } bool init(void); bool initWithLuaState(lua_State *L); lua_State *_state; int _callFromLua; bool _xxteaEnabled; char* _xxteaKey; int _xxteaKeyLen; char* _xxteaSign; int _xxteaSignLen;};NS_CC_END#endif // __CC_LUA_STACK_H_
下面是实现
#include "CCLuaStack.h"#include "tolua_fix.h"#include "external/xxtea/xxtea.h"extern "C" {#include "lua.h"#include "tolua++.h"#include "lualib.h"#include "lauxlib.h"}#include "Cocos2dxLuaLoader.h"#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)#include "platform/ios/CCLuaObjcBridge.h"#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include "platform/android/CCLuaJavaBridge.h"#endif#include "LuaOpengl.h"#include "LuaScriptHandlerMgr.h"#include "lua_cocos2dx_auto.hpp"#include "lua_cocos2dx_manual.hpp"#include "LuaBasicConversions.h"#include "lua_cocos2dx_deprecated.h"#include "lua_cocos2dx_physics_auto.hpp"#include "lua_cocos2dx_physics_manual.hpp"#include "lua_cocos2dx_experimental_auto.hpp"#include "lua_cocos2dx_experimental_manual.hpp"namespace {int lua_print(lua_State * luastate)//打印当前lua栈的里面值的类型{ int nargs = lua_gettop(luastate); std::string t; for (int i=1; i <= nargs; i++) { if (lua_istable(luastate, i)) t += "table"; else if (lua_isnone(luastate, i)) t += "none"; else if (lua_isnil(luastate, i)) t += "nil"; else if (lua_isboolean(luastate, i)) { if (lua_toboolean(luastate, i) != 0) t += "true"; else t += "false"; } else if (lua_isfunction(luastate, i)) t += "function"; else if (lua_islightuserdata(luastate, i)) t += "lightuserdata"; else if (lua_isthread(luastate, i)) t += "thread"; else { const char * str = lua_tostring(luastate, i); if (str) t += lua_tostring(luastate, i); else t += lua_typename(luastate, lua_type(luastate, i)); } if (i!=nargs) t += "\t"; } CCLOG("[LUA-print] %s", t.c_str()); return 0;} int lua_release_print(lua_State * L){ int nargs = lua_gettop(L); std::string t; for (int i=1; i <= nargs; i++) { if (lua_istable(L, i)) t += "table"; else if (lua_isnone(L, i)) t += "none"; else if (lua_isnil(L, i)) t += "nil"; else if (lua_isboolean(L, i)) { if (lua_toboolean(L, i) != 0) t += "true"; else t += "false"; } else if (lua_isfunction(L, i)) t += "function"; else if (lua_islightuserdata(L, i)) t += "lightuserdata"; else if (lua_isthread(L, i)) t += "thread"; else { const char * str = lua_tostring(L, i); if (str) t += lua_tostring(L, i); else t += lua_typename(L, lua_type(L, i)); } if (i!=nargs) t += "\t"; } log("[LUA-print] %s", t.c_str()); return 0;}}NS_CC_BEGINLuaStack::~LuaStack(){ if (nullptr != _state) { lua_close(_state);//关闭lua栈 }}LuaStack *LuaStack::create(void){ LuaStack *stack = new (std::nothrow) LuaStack();//以不抛出异常的方式创建lua栈 stack->init(); stack->autorelease();//加入到自动释放池 return stack;}LuaStack *LuaStack::attach(lua_State *L){ LuaStack *stack = new (std::nothrow) LuaStack(); stack->initWithLuaState(L); stack->autorelease(); return stack;}//这个函数很多看不懂,先记录这里bool LuaStack::init(void){ _state = lua_open();//通过lua_open打开很多lua的标准库,供lua栈的使用 luaL_openlibs(_state); toluafix_open(_state); // Register our version of the global "print" function const luaL_reg global_functions [] = { {"print", lua_print}, {"release_print",lua_release_print}, {nullptr, nullptr} }; luaL_register(_state, "_G", global_functions);//将上面的两个函数注册进lua的全局table里面 g_luaType.clear(); register_all_cocos2dx(_state); tolua_opengl_open(_state); register_all_cocos2dx_manual(_state); register_all_cocos2dx_module_manual(_state); register_all_cocos2dx_math_manual(_state); register_all_cocos2dx_experimental(_state); register_all_cocos2dx_experimental_manual(_state); register_glnode_manual(_state);#if CC_USE_PHYSICS register_all_cocos2dx_physics(_state); register_all_cocos2dx_physics_manual(_state);#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC) LuaObjcBridge::luaopen_luaoc(_state);#endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) LuaJavaBridge::luaopen_luaj(_state);#endif register_all_cocos2dx_deprecated(_state); register_all_cocos2dx_manual_deprecated(_state); tolua_script_handler_mgr_open(_state); // add cocos2dx loader addLuaLoader(cocos2dx_lua_loader); return true;}bool LuaStack::initWithLuaState(lua_State *L){ _state = L; return true;}// lua_getglobal将全局变量avg的值入栈//lua_getfield把 t[k] 值压入堆栈,这里的 t 是指有效索引 index 指向的值。//llua_pop(_state, 2);从堆栈中弹出两个元素void LuaStack::addSearchPath(const char* path){ lua_getglobal(_state, "package"); /* L: package */ lua_getfield(_state, -1, "path"); /* get package.path, L: package path */ const char* cur_path = lua_tostring(_state, -1); lua_pushfstring(_state, "%s;%s/?.lua", cur_path, path); /* L: package path newpath */ lua_setfield(_state, -3, "path"); /* package.path = newpath, L: package path */ lua_pop(_state, 2); /* L: - */}//这个里面涉及到的元方法看不太懂void LuaStack::addLuaLoader(lua_CFunction func){ if (!func) return; // stack content after the invoking of the function // get loader table lua_getglobal(_state, "package"); /* L: package */ lua_getfield(_state, -1, "loaders"); /* L: package, loaders */ // insert loader into index 2 lua_pushcfunction(_state, func); /* L: package, loaders, func */ for (int i = (int)(lua_objlen(_state, -2) + 1); i > 2; --i) { lua_rawgeti(_state, -2, i - 1); /* L: package, loaders, func, function */ // we call lua_rawgeti, so the loader table now is at -3 lua_rawseti(_state, -3, i); /* L: package, loaders, func */ } lua_rawseti(_state, -2, 2); /* L: package, loaders */ // set loaders into package lua_setfield(_state, -2, "loaders"); /* L: package */ lua_pop(_state, 1);}void LuaStack::removeScriptObjectByObject(Ref* pObj){ toluafix_remove_ccobject_by_refid(_state, pObj->_luaID);}void LuaStack::removeScriptHandler(int nHandler){ toluafix_remove_function_by_refid(_state, nHandler);}//调用辅助库里面的luaL_loadstring执行一段字符串代码int LuaStack::executeString(const char *codes){ luaL_loadstring(_state, codes); return executeFunction(0);}//调用辅助库里面的luaLoadBuffer执行lua脚本文件int LuaStack::executeScriptFile(const char* filename){ CCAssert(filename, "CCLuaStack::executeScriptFile() - invalid filename"); FileUtils *utils = FileUtils::getInstance(); std::string fullPath = utils->fullPathForFilename(filename); Data data = utils->getDataFromFile(fullPath); int rn = 0; if (!data.isNull()) { if (luaLoadBuffer(_state, (const char*)data.getBytes(), (int)data.getSize(), fullPath.c_str()) == 0) { rn = executeFunction(0); } } return rn;}//用这个lua_getglobal直接执行这个函数int LuaStack::executeGlobalFunction(const char* functionName){ lua_getglobal(_state, functionName); /* query function by name, stack: function */ if (!lua_isfunction(_state, -1)) { CCLOG("[LUA ERROR] name '%s' does not represent a Lua function", functionName); lua_pop(_state, 1); return 0; } return executeFunction(0);}//栈清零void LuaStack::clean(void){ lua_settop(_state, 0);}void LuaStack::pushInt(int intValue){ lua_pushinteger(_state, intValue);}void LuaStack::pushFloat(float floatValue){ lua_pushnumber(_state, floatValue);}void LuaStack::pushLong(long longValue){ lua_pushnumber(_state, longValue);}void LuaStack::pushBoolean(bool boolValue){ lua_pushboolean(_state, boolValue);}void LuaStack::pushString(const char* stringValue){ lua_pushstring(_state, stringValue);}void LuaStack::pushString(const char* stringValue, int length){ lua_pushlstring(_state, stringValue, length);}void LuaStack::pushNil(void){ lua_pushnil(_state);}//压入一个Ref对象void LuaStack::pushObject(Ref* objectValue, const char* typeName){ toluafix_pushusertype_ccobject(_state, objectValue->_ID, &objectValue->_luaID, objectValue, typeName);}//压入一个lua类型的值,根据什么值调用对应的逻辑代码void LuaStack::pushLuaValue(const LuaValue& value){ const LuaValueType type = value.getType(); if (type == LuaValueTypeInt) { return pushInt(value.intValue()); } else if (type == LuaValueTypeFloat) { return pushFloat(value.floatValue()); } else if (type == LuaValueTypeBoolean) { return pushBoolean(value.booleanValue()); } else if (type == LuaValueTypeString) { return pushString(value.stringValue().c_str()); } else if (type == LuaValueTypeDict) { pushLuaValueDict(value.dictValue()); } else if (type == LuaValueTypeArray) { pushLuaValueArray(value.arrayValue()); } else if (type == LuaValueTypeObject) { pushObject(value.ccobjectValue(), value.getObjectTypename().c_str()); }}//将一个table压入栈//lua_newtable创建一个空table并压入栈中//随后循环这个table,将value压入栈//lua_rawset(_state, -3);直接在table里面赋值,不触发元方法void LuaStack::pushLuaValueDict(const LuaValueDict& dict){ lua_newtable(_state); /* L: table */ for (LuaValueDictIterator it = dict.begin(); it != dict.end(); ++it) { lua_pushstring(_state, it->first.c_str()); /* L: table key */ pushLuaValue(it->second); /* L: table key value */ lua_rawset(_state, -3); /* table.key = value, L: table */ }}void LuaStack::pushLuaValueArray(const LuaValueArray& array){ lua_newtable(_state); /* L: table */ int index = 1; for (LuaValueArrayIterator it = array.begin(); it != array.end(); ++it) { pushLuaValue(*it); /* L: table value */ lua_rawseti(_state, -2, index); /* table[index] = value, L: table */ ++index; }}bool LuaStack::pushFunctionByHandler(int nHandler){ toluafix_get_function_by_refid(_state, nHandler); /* L: ... func */ if (!lua_isfunction(_state, -1)) { CCLOG("[LUA ERROR] function refid '%d' does not reference a Lua function", nHandler); lua_pop(_state, 1); return false; } return true;}int LuaStack::executeFunction(int numArgs){ int functionIndex = -(numArgs + 1); if (!lua_isfunction(_state, functionIndex)) { CCLOG("value at stack [%d] is not function", functionIndex); lua_pop(_state, numArgs + 1); // remove function and arguments return 0; } int traceback = 0; lua_getglobal(_state, "__G__TRACKBACK__"); /* L: ... func arg1 arg2 ... G */ if (!lua_isfunction(_state, -1)) { lua_pop(_state, 1); /* L: ... func arg1 arg2 ... */ } else { lua_insert(_state, functionIndex - 1); /* L: ... G func arg1 arg2 ... */ traceback = functionIndex - 1; } int error = 0; ++_callFromLua; error = lua_pcall(_state, numArgs, 1, traceback); /* L: ... [G] ret */ --_callFromLua; if (error) { if (traceback == 0) { CCLOG("[LUA ERROR] %s", lua_tostring(_state, - 1)); /* L: ... error */ lua_pop(_state, 1); // remove error message from stack } else /* L: ... G error */ { lua_pop(_state, 2); // remove __G__TRACKBACK__ and error message from stack } return 0; } // get return value int ret = 0; if (lua_isnumber(_state, -1)) { ret = (int)lua_tointeger(_state, -1); } else if (lua_isboolean(_state, -1)) { ret = (int)lua_toboolean(_state, -1); } // remove return value from stack lua_pop(_state, 1); /* L: ... [G] */ if (traceback) { lua_pop(_state, 1); // remove __G__TRACKBACK__ from stack /* L: ... */ } return ret;}int LuaStack::executeFunctionByHandler(int nHandler, int numArgs){ int ret = 0; if (pushFunctionByHandler(nHandler)) /* L: ... arg1 arg2 ... func */ { if (numArgs > 0) { lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */ } ret = executeFunction(numArgs); } lua_settop(_state, 0); return ret;}bool LuaStack::handleAssert(const char *msg, const char *cond, const char *file, int line){ if (_callFromLua == 0) return false; const char *msgErr = msg ? msg : "unknown";lua_pushstring(_state, "__G__TRACKBACK__");lua_rawget(_state, LUA_GLOBALSINDEX);lua_pushstring(_state, msgErr);lua_call(_state, 1, 0); if (cond && file) { lua_pushfstring(_state, "\n==============\nASSERT FAILED ON LUA EXECUTE:\n File: %s\n Line: %d\n\n Expression: %s\n==============", file, line, cond); } else { lua_pushfstring(_state, "\n==============\nASSERT FAILED ON LUA EXECUTE: %s\n==============", msgErr); }lua_error(_state); return true;}int LuaStack::reallocateScriptHandler(int nHandler){ LUA_FUNCTION nNewHandle = -1; if (pushFunctionByHandler(nHandler)) { nNewHandle = toluafix_ref_function(_state,lua_gettop(_state),0); }/* toluafix_get_function_by_refid(_state,nNewHandle); if (!lua_isfunction(_state, -1)) { CCLOG("Error!"); } lua_settop(_state, 0);*/ return nNewHandle;}int LuaStack::executeFunctionReturnArray(int handler,int numArgs,int numResults,__Array& resultArray){ int top = lua_gettop(_state); if (pushFunctionByHandler(handler)) /* L: ... arg1 arg2 ... func */ { if (numArgs > 0) { lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */ } int functionIndex = -(numArgs + 1); if (!lua_isfunction(_state, functionIndex)) { CCLOG("value at stack [%d] is not function", functionIndex); lua_pop(_state, numArgs + 1); // remove function and arguments lua_settop(_state,top); return 0; } int traceback = 0; lua_getglobal(_state, "__G__TRACKBACK__"); /* L: ... func arg1 arg2 ... G */ if (!lua_isfunction(_state, -1)) { lua_pop(_state, 1); /* L: ... func arg1 arg2 ... */ } else { lua_insert(_state, functionIndex - 1); /* L: ... G func arg1 arg2 ... */ traceback = functionIndex - 1; } int error = 0; ++_callFromLua; error = lua_pcall(_state, numArgs, numResults, traceback); /* L: ... [G] ret1 ret2 ... retResults*/ --_callFromLua; if (error) { if (traceback == 0) { CCLOG("[LUA ERROR] %s", lua_tostring(_state, - 1)); /* L: ... error */ lua_pop(_state, 1); // remove error message from stack } else /* L: ... G error */ { lua_pop(_state, 2); // remove __G__TRACKBACK__ and error message from stack } lua_settop(_state,top); return 0; } // get return value,don't pass LUA_MULTRET to numResults, if (numResults <= 0) { lua_settop(_state,top); return 0; } for (int i = 0 ; i < numResults; i++) { if (lua_type(_state, -1) == LUA_TBOOLEAN) { bool value = lua_toboolean(_state, -1); resultArray.addObject(Bool::create(value)) ; }else if (lua_type(_state, -1) == LUA_TNUMBER) { double value = lua_tonumber(_state, -1); resultArray.addObject(Double::create(value)); }else if (lua_type(_state, -1) == LUA_TSTRING) { const char* value = lua_tostring(_state, -1); resultArray.addObject(String::create(value)); }else{ resultArray.addObject(static_cast<Ref*>(tolua_tousertype(_state, -1, nullptr))); } // remove return value from stack lua_pop(_state, 1); /* L: ... [G] ret1 ret2 ... ret*/ } /* L: ... [G]*/ if (traceback) { lua_pop(_state, 1); // remove __G__TRACKBACK__ from stack /* L: ... */ } } lua_settop(_state,top); return 1;}int LuaStack::executeFunction(int handler, int numArgs, int numResults, const std::function<void(lua_State*,int)>& func){ if (pushFunctionByHandler(handler)) /* L: ... arg1 arg2 ... func */ { if (numArgs > 0) { lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */ } int functionIndex = -(numArgs + 1); if (!lua_isfunction(_state, functionIndex)) { CCLOG("value at stack [%d] is not function", functionIndex); lua_pop(_state, numArgs + 1); // remove function and arguments return 0; } int traceCallback = 0; lua_getglobal(_state, "__G__TRACKBACK__"); /* L: ... func arg1 arg2 ... G */ if (!lua_isfunction(_state, -1)) { lua_pop(_state, 1); /* L: ... func arg1 arg2 ... */ } else { lua_insert(_state, functionIndex - 1); /* L: ... G func arg1 arg2 ... */ traceCallback = functionIndex - 1; } int error = 0; ++_callFromLua; error = lua_pcall(_state, numArgs, numResults, traceCallback); /* L: ... [G] ret1 ret2 ... retResults*/ --_callFromLua; if (error) { if (traceCallback == 0) { CCLOG("[LUA ERROR] %s", lua_tostring(_state, - 1)); /* L: ... error */ lua_pop(_state, 1); // remove error message from stack } else /* L: ... G error */ { lua_pop(_state, 2); // remove __G__TRACKBACK__ and error message from stack } return 0; } // get return value,don't pass LUA_MULTRET to numResults, do { if (numResults <= 0 || nullptr == func) break; func(_state, numResults); } while (0); if (traceCallback) { lua_pop(_state, 1); // remove __G__TRACKBACK__ from stack /* L: ... */ } } return 1;}int LuaStack::reload(const char* moduleFileName){ if (nullptr == moduleFileName || strlen(moduleFileName) == 0) { CCLOG("moudulFileName is null"); return 1; } lua_getglobal(_state, "package"); /* L: package */ lua_getfield(_state, -1, "loaded"); /* L: package loaded */ lua_pushstring(_state, moduleFileName); lua_gettable(_state, -2); /* L:package loaded module */ if (!lua_isnil(_state, -1)) { lua_pushstring(_state, moduleFileName); /* L:package loaded module name */ lua_pushnil(_state); /* L:package loaded module name nil*/ lua_settable(_state, -4); /* L:package loaded module */ } lua_pop(_state, 3); std::string name = moduleFileName; std::string require = "require \'" + name + "\'"; return executeString(require.c_str());}void LuaStack::setXXTEAKeyAndSign(const char *key, const char *sign){ int keyLen = (int)strlen(key); int signLen = (int)strlen(sign); cleanupXXTEAKeyAndSign(); if (key && keyLen && sign && signLen) { _xxteaKey = (char*)malloc(keyLen); memcpy(_xxteaKey, key, keyLen); _xxteaKeyLen = keyLen; _xxteaSign = (char*)malloc(signLen); memcpy(_xxteaSign, sign, signLen); _xxteaSignLen = signLen; _xxteaEnabled = true; } else { _xxteaEnabled = false; }}void LuaStack::cleanupXXTEAKeyAndSign(){ if (_xxteaKey) { free(_xxteaKey); _xxteaKey = nullptr; _xxteaKeyLen = 0; } if (_xxteaSign) { free(_xxteaSign); _xxteaSign = nullptr; _xxteaSignLen = 0; }}const char* LuaStack::getXXTEAKey(int *len){ if (_xxteaEnabled && _xxteaKey) { if (len) { *len = _xxteaKeyLen; } return _xxteaKey; } return nullptr;}const char* LuaStack::getXXTEASign(int *len){ if (_xxteaEnabled && _xxteaSign) { if (len) { *len = _xxteaSignLen; } return _xxteaSign; } return nullptr;}int LuaStack::loadChunksFromZIP(const char *zipFilePath){ pushString(zipFilePath); luaLoadChunksFromZIP(_state); int ret = lua_toboolean(_state, -1); lua_pop(_state, 1); return ret;}int LuaStack::luaLoadChunksFromZIP(lua_State *L){ if (lua_gettop(L) < 1) { CCLOG("luaLoadChunksFromZIP() - invalid arguments"); return 0; } const char *zipFilename = lua_tostring(L, -1); lua_settop(L, 0); FileUtils *utils = FileUtils::getInstance(); std::string zipFilePath = utils->fullPathForFilename(zipFilename); LuaStack *stack = this; do { ssize_t size = 0; void *buffer = nullptr; unsigned char *zipFileData = utils->getFileData(zipFilePath.c_str(), "rb", &size); ZipFile *zip = nullptr; bool isXXTEA = stack && stack->_xxteaEnabled && zipFileData; for (int i = 0; isXXTEA && i < stack->_xxteaSignLen && i < size; ++i) { isXXTEA = zipFileData[i] == stack->_xxteaSign[i]; } if (isXXTEA) { // decrypt XXTEA xxtea_long len = 0; buffer = xxtea_decrypt(zipFileData + stack->_xxteaSignLen, (xxtea_long)size - (xxtea_long)stack->_xxteaSignLen, (unsigned char*)stack->_xxteaKey, (xxtea_long)stack->_xxteaKeyLen, &len); free(zipFileData); zipFileData = nullptr; zip = ZipFile::createWithBuffer(buffer, len); } else { if (zipFileData) { zip = ZipFile::createWithBuffer(zipFileData, size); } } if (zip) { CCLOG("lua_loadChunksFromZIP() - load zip file: %s%s", zipFilePath.c_str(), isXXTEA ? "*" : ""); lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); int count = 0; std::string filename = zip->getFirstFilename(); while (filename.length()) { ssize_t bufferSize = 0; unsigned char *zbuffer = zip->getFileData(filename.c_str(), &bufferSize); if (bufferSize) { if (stack->luaLoadBuffer(L, (char*)zbuffer, (int)bufferSize, filename.c_str()) == 0) { lua_setfield(L, -2, filename.c_str()); ++count; } free(zbuffer); } filename = zip->getNextFilename(); } CCLOG("lua_loadChunksFromZIP() - loaded chunks count: %d", count); lua_pop(L, 2); lua_pushboolean(L, 1); delete zip; } else { CCLOG("lua_loadChunksFromZIP() - not found or invalid zip file: %s", zipFilePath.c_str()); lua_pushboolean(L, 0); } if (zipFileData) { free(zipFileData); } if (buffer) { free(buffer); } } while (0); return 1;}int LuaStack::luaLoadBuffer(lua_State *L, const char *chunk, int chunkSize, const char *chunkName){ int r = 0; if (_xxteaEnabled && strncmp(chunk, _xxteaSign, _xxteaSignLen) == 0) { // decrypt XXTEA xxtea_long len = 0; unsigned char* result = xxtea_decrypt((unsigned char*)chunk + _xxteaSignLen, (xxtea_long)chunkSize - _xxteaSignLen, (unsigned char*)_xxteaKey, (xxtea_long)_xxteaKeyLen, &len); r = luaL_loadbuffer(L, (char*)result, len, chunkName); free(result); } else { r = luaL_loadbuffer(L, chunk, chunkSize, chunkName); } #if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0 if (r) { switch (r) { case LUA_ERRSYNTAX: CCLOG("[LUA ERROR] load \"%s\", error: syntax error during pre-compilation.", chunkName); break; case LUA_ERRMEM: CCLOG("[LUA ERROR] load \"%s\", error: memory allocation error.", chunkName); break; case LUA_ERRFILE: CCLOG("[LUA ERROR] load \"%s\", error: cannot open/read file.", chunkName); break; default: CCLOG("[LUA ERROR] load \"%s\", error: unknown.", chunkName); } }#endif return r;}NS_CC_END
0 0
- CCLuaStack.h详解
- cocos2dx-Lua学习笔记:CCLuaStack
- reg51.h 详解
- H.264 标准详解
- H.264详解(二)
- H.264详解(一)
- H.264详解
- #include“stdafx.h”详解
- H.264详解
- stdarg.h详解
- h:panelGrid 属性详解
- #include“stdafx.h”详解
- reg51.h 详解
- linnids.h 详解
- CGGeometry.h详解
- H.264详解
- configure -h 参数详解
- H.264 Nalu 详解
- 5016. 数列
- sort对二维字符数组排序
- React Native 中POST请求参数传递
- new写在循环内部和外部的区别
- Android Dialog圆角问题
- CCLuaStack.h详解
- 北航计算机机试07字符串统计
- 内存空间
- web-homework-2
- Java
- 工作中用到的零散知识-链接汇总
- Liunx常用命令解析(一)--导航命令
- Oracle lsnrctl命令使用总结
- Ubuntu搭建Caffe(仅CPU)