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下不能用