• 技术文章 >数据库 >mysql教程

    cocos2dx lua文件的加载问题

    2016-06-07 15:49:55原创526

    lua库函数里面自带有加载lua文件的几个函数 static const lua_CFunction package_loaders[] = { lj_cf_package_loader_preload, lj_cf_package_loader_lua, lj_cf_package_loader_c, lj_cf_package_loader_croot, NULL }; 在lua的源码lib_package.c文件可以

    lua库函数里面自带有加载lua文件的几个函数

    static const lua_CFunction package_loaders[] =

    {
    lj_cf_package_loader_preload,
    lj_cf_package_loader_lua,
    lj_cf_package_loader_c,
    lj_cf_package_loader_croot,
    NULL

    };

    在lua的源码lib_package.c文件可以找到。其中还包含了一个初始化函数

    LUALIB_API int luaopen_package(lua_State *L)
    {
    int i;
    int noenv;
    luaL_newmetatable(L, "_LOADLIB");
    lj_lib_pushcf(L, lj_cf_package_unloadlib, 1);
    lua_setfield(L, -2, "__gc");
    luaL_register(L, LUA_LOADLIBNAME, package_lib);
    lua_pushvalue(L, -1);
    lua_replace(L, LUA_ENVIRONINDEX);
    lua_createtable(L, sizeof(package_loaders)/sizeof(package_loaders[0])-1, 0);
    for (i = 0; package_loaders[i] != NULL; i++) {
    lj_lib_pushcf(L, package_loaders[i], 1);
    lua_rawseti(L, -2, i+1);
    }
    lua_setfield(L, -2, "loaders");
    lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
    noenv = lua_toboolean(L, -1);
    lua_pop(L, 1);
    setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT, noenv);
    setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT, noenv);
    lua_pushliteral(L, LUA_PATH_CONFIG);
    lua_setfield(L, -2, "config");
    luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
    lua_setfield(L, -2, "loaded");
    luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4);
    lua_setfield(L, -2, "preload");
    lua_pushvalue(L, LUA_GLOBALSINDEX);
    luaL_register(L, NULL, package_global);
    lua_pop(L, 1);
    return 1;
    }

    这个函数会在lua打开所有库的时候调用(即 luaL_openlibs(m_state)时)。仔细看里面的代码会发现,package_loaders里面的所有函数都被存在package.loaders的全局表中。

    cocos2dx官方在这个全局表里面增加了一个自己实现的加载函数,即Cocos2dxLuaLoader。具体实现可参看CCLuaStack.cpp文件。

    void CCLuaStack::addLuaLoader(lua_CFunction func)
    {
    if (!func) return;

    // stack content after the invoking of the function
    // get loader table
    lua_getglobal(m_state, "package"); /* L: package */
    lua_getfield(m_state, -1, "loaders"); /* L: package, loaders */

    // insert loader into index 2
    lua_pushcfunction(m_state, func); /* L: package, loaders, func */
    for (int i = lua_objlen(m_state, -2) + 1; i > 2; --i)
    {
    lua_rawgeti(m_state, -2, i - 1); /* L: package, loaders, func, function */
    // we call lua_rawgeti, so the loader table now is at -3
    lua_rawseti(m_state, -3, i); /* L: package, loaders, func */
    }
    lua_rawseti(m_state, -2, 2); /* L: package, loaders */

    // set loaders into package
    lua_setfield(m_state, -2, "loaders"); /* L: package */

    lua_pop(m_state, 1);
    }

    这个函数将cocosdx自带的load函数存到了package.loaders表的第二个索引处。即插在 lj_cf_package_loader_preload和
    lj_cf_package_loader_lua之间。



    ---------------------------------------------------------

    介绍完上面这些背景之后,我们再看看实际加载过程中,require函数在android下面和win下面需求路径不同的问题。

    在android环境中,require实际起作用的加载函数是官方自带的Cocos2dxLuaLoader函数,而且路径必须是相对assets下的完整路径。lua里面自带几个加载函数都会加载不到(具体原因不明,可能跟lua的相对路径不在assets下有关,即使加path路径也没用(原因是android下的lua文件是在APK压缩包里面去找,不存在绝对路径,所以lua会加载不到))。不相信的童鞋可以把CCLuaStack.cpp中的addLuaLoader注释掉,你会发现所有的require都找不到文件

    在win环境中,可以通过addSearchPath的方式,在package.path里面增加lua文件的查找路径,由于添加的是绝对路径,所以你会发现就算你require里面没填完整路径,lua也会自动在path里去找相关的文件进行加载。(但是Cocos2dxLuaLoader这个函数其实不能正常加载,所以你可能会看到,log里面显示没加载到,实际已经加载成功的现象。这里加载成功是lua自带的加载函数实现的)

    结论:

    尽量都用assets下的完整路径,这样Cocos2dxLuaLoader都会加载的到,不会出现误提示。win下可以用addSearchPath的方式,android下不能用

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:Oracle数据库11g新特性:SQL Access Advisor 下一篇:zoj 1158 判断2线段完全相交

    相关文章推荐

    • 必须要了解MySQL索引的坑• 一起聊聊MYSQL中锁的各种模式与类型• MySQL之SQL优化、索引优化、锁机制、主从复制(图文详解)• docker和jenkins是什么• mysql中怎么调用存储过程

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网