源码已经更新在优快云的码库里:
git clone https://gitcode.com/funsion/CLua.git
在src文件夹下的loadlib.c 动态库加载器函数,此模块包含适用于具有dlfcn的Unix系统的loadlib实现,适用于Windows系统的实现,以及适用于其他系统的占位符实现。
增加中文版luaL_Reg pk_funcs 包的使用列表,保留英文版luaL_Reg pk_funcs 包的使用列表。
原始的代码为:
static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib},
{"searchpath", ll_searchpath},
/* placeholders */
{"preload", NULL},
{"cpath", NULL},
{"path", NULL},
{"searchers", NULL},
{"loaded", NULL},
{NULL, NULL}
};
static const luaL_Reg ll_funcs[] = {
{"require", ll_require},
{NULL, NULL}
};
更改成以下代码:
static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib}, {"加载库", ll_loadlib}, // 中文别名
{"searchpath", ll_searchpath}, {"搜索路径", ll_searchpath}, // 中文别名
{"preload", NULL}, {"预加载", NULL}, // 中文别名
{"cpath", NULL}, {"C路径", NULL}, // 中文别名
{"path", NULL}, {"路径", NULL}, // 中文别名
{"searchers", NULL}, {"搜索器", NULL}, // 中文别名
{"loaded", NULL}, {"已加载", NULL}, // 中文别名
{NULL, NULL}
};
更改搜索器的逻辑,以便支持中英文。
static void createsearcherstable (lua_State *L) {
static const lua_CFunction searchers[] = {
searcher_preload,
searcher_Lua,
searcher_C,
searcher_Croot,
NULL
};
int i;
/* create 'searchers' table */
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
/* fill it with predefined searchers */
for (i=0; searchers[i] != NULL; i++) {
lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
lua_pushcclosure(L, searchers[i], 1);
lua_rawseti(L, -2, i+1);
}
lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
}
static void createsearcherstable (lua_State *L) {
static const lua_CFunction searchers[] = {
searcher_preload,
searcher_Lua,
searcher_C,
searcher_Croot,
NULL
};
int i;
/* 创建搜索器表 */
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); // 表在栈顶(位置 -1)
/* 填充搜索器 */
for (i = 0; searchers[i] != NULL; i++) {
lua_pushvalue(L, -2); // 上值:package 表(位置 -2)
lua_pushcclosure(L, searchers[i], 1);
lua_rawseti(L, -2, i + 1); // 设置到搜索器表(位置 -2)
}
/* 关键修复:复制表的引用并绑定字段 */
lua_pushvalue(L, -1); // 复制搜索器表到栈顶(位置 -1)
lua_setfield(L, -3, "searchers"); // package.searchers = 搜索器表(父表在 -3)
lua_pushvalue(L, -1); // 再次复制搜索器表到栈顶(位置 -1)
lua_setfield(L, -3, "搜索器"); // package.搜索器 = 搜索器表(父表在 -3)
lua_pop(L, 1); // 弹出原始搜索器表(位置 -1)
}
增加路径的映射,以便支持中英文。
LUAMOD_API int luaopen_package (lua_State *L) {
createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* set paths */
setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT);
setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
/* store config information */
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
lua_setfield(L, -2, "config");
/* set field 'loaded' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_setfield(L, -2, "loaded");
/* set field 'preload' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_setfield(L, -2, "preload");
lua_pushglobaltable(L);
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */
}
LUAMOD_API int luaopen_package (lua_State *L) {
createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* set paths */
setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT);
setpath(L, "路径", LUA_PATH_VAR, LUA_PATH_DEFAULT);
setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
setpath(L, "c路径", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
/* store config information */
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
lua_setfield(L, -2, "config");
/* set field 'loaded' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_setfield(L, -2, "loaded");
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_setfield(L, -2, "已加载");
/* set field 'preload' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_setfield(L, -2, "preload");
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_setfield(L, -2, "预加载");
lua_pushglobaltable(L);
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */
}
为了保证中英文 函数都可以加载,以便你可以复制英文原码来进行更改。所以保留了英文版 函数名列表,这样就能使用两种文的函数。
{"require", ll_require}, // 引入
{"引入", ll_require}, // 和require相同,但是使用中文名称
其实它们都是加载同样的库名,算是加载了2次,以Lua内部算法,应该只会加载一次。
更改完之后,同样需要重新编译Lua的源码,实现以上列出的关键词的中文化。
注意,在Window系统下编译Lua, 最好将所有Lua的源码,重新保存成ANSI格式的文件,刚下载的默认的源码会是UTF-8格式的。
这个事情说三遍,
1,不然就会出现,Window下的UTF-8源码可编译,但Shell里的中文输出会乱码。
2,要不然就是Window的ANSI源码不可编译(假如你没做以上步骤),
3,如果是用ANSI格式的源码编译的Lua.exe,对应的,你在Window下写的Lua程序也是需要保存成ANSI格式的。这样就可以在Shell里输出正确的中文显示。
测试代码:
-- 验证字段是否存在且为表
print("package.searchers 类型:", type(package.searchers)) --> table
print("package.搜索器 类型:", type(package.搜索器)) --> table
-- 验证两个字段指向同一个表
print("是否同一表:", package.searchers == package.搜索器) --> true
-- 遍历中文搜索器列表
print("\n中文搜索器列表:")
for _, searcher in ipairs(package.搜索器) do
print(searcher)
end
-- 验证 path 和 路径 是否同步
print("package.path 原始值:", package.path)
print("package.路径 原始值:", package.路径)
-- 修改英文路径,检查中文路径是否同步
package.path = package.path .. ";./mylua/?.lua"
print("\n修改后 package.path:", package.path)
print("修改后 package.路径:", package.路径)
-- 修改中文路径,检查英文路径是否同步
package.路径 = "/usr/local/lua/?.lua"
print("\n再次修改后 package.path:", package.path)
print("再次修改后 package.路径:", package.路径)
-- 验证 cpath 和 C路径 是否同步
print("\npackage.cpath 原始值:", package.cpath)
print("package.C路径 原始值:", package.C路径)
-- 修改英文C路径,检查中文C路径
package.cpath = package.cpath .. ";./myclib/?.so"
print("\n修改后 package.cpath:", package.cpath)
print("修改后 package.C路径:", package.C路径)
-- 修改中文C路径,检查英文C路径
package.C路径 = "/usr/local/lua/?.so"
print("\n再次修改后 package.cpath:", package.cpath)
print("再次修改后 package.C路径:", package.C路径)
-- 验证 loaded 和 已加载 是否指向同一个表
print("\npackage.loaded 类型:", type(package.loaded))
print("package.已加载 类型:", type(package.已加载))
-- 加载一个模块(例如 math)
require "math"
print("\npackage.loaded.math 是否存在:", package.loaded.math ~= nil)
print("package.已加载.math 是否存在:", package.已加载.math ~= nil)
-- 通过中文名删除模块
package.已加载.math = nil
print("\n删除后 package.loaded.math:", package.loaded.math)
-- 验证 preload 和 预加载 是否同步
local function mymodule() return "Hello" end
-- 通过英文名添加预加载模块
package.preload.mymodule = mymodule
print("\npackage.preload.mymodule 类型:", type(package.preload.mymodule))
print("package.预加载.mymodule 类型:", type(package.预加载.mymodule))
-- 通过中文名调用预加载模块
local ok, msg = pcall(require, "mymodule")
print("\n通过 require 'mymodule' 调用结果:", ok, msg)
-- 验证 loadlib 和 加载库 是否为同一函数
print("\npackage.loadlib 类型:", type(package.loadlib))
print("package.加载库 类型:", type(package.加载库))
-- 尝试加载一个不存在的库(预期失败)
local f, err = package.加载库("nonexistent.dll", "init")
print("\n加载不存在的库:", f, err)
-- 验证访问未定义的中文字段(预期返回 nil)
print("\n访问无效字段 package.不存在字段:", package.不存在字段)
-- 验证非字符串字段赋值(预期报错)
local ok, msg = pcall(function()
package.路径 = 123 -- 错误:路径必须是字符串
end)
print("\n非法赋值测试:", ok, msg)