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
原创粉丝点击