您好,欢迎访问一九零五行业门户网

cocos2dx lua文件的加载问题

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下不能用
其它类似信息

推荐信息