lua_component 自載程式 require('klass.c_str() ) C_API ??
可省去 rime.lua 中編輯 require 也可以不放在global
ex:
# lua/date_translator.lua
#custom.yaml
patch:
engine/translators/@next: lua_translator@date_translator@date
在 https://github.com/hchunhui/librime-lua/blob/8b37d5541b0341a07ed7517c78df1a09268001fd/src/lua_gears.cc#L36-L40
插入
if (lua_type(L,-1) == LUA_TNIL) {
lua_pop(L, 1);
//
// lua_code require(t.klass.c_str())
}
用lua 自載
function auto_load(env)
local config=env.engine.schema.config
for _,path in next, {"processors","segments","translators","filters"} do
local config_list= config:get_list("engine/" .. path)
for i=0,config_list.size do
local module = config:get_value_at(i):match("^lua_%a+@(.*)$")
module= module:match("^(.+)@.+$") or module
_G[module] =_G[module] and _G[module] or require(module)
end
end
end
原本的设计是不强求 lua_component 必定对应一个可以被 require 的文件,而是对应一个 global function(或者 table)就可以。这样相比 require 自载可以理灵活,比如简单的 component 全部写到 rime.lua 就可以了;有些复杂的功能需要在一个文件里面写多个 component 。这两种情况自载都不容易做到。
不过这个想法很合理:需要有某种办法能自动地载入他人做好的功能模块,而不是要用户自己编辑 rime.lua,类似 #151 的要求。
我剛才用 luaL_dostring() ok,前提是 klass 要和 moduel 同名 #151 是要 lua 初始化lua_state 時載入路逕下的所有檔案 這是在 create lua_component時發現 找不到 _G[klass]
載入成功
用 luaL_requiref(L, t.klass, nullptr, -1) 會發生 segmentation fault (core dumped)
static void raw_init(lua_State *L, const Ticket &t,
an<LuaObj> *env, an<LuaObj> *func, an<LuaObj> *fini) {
lua_newtable(L);
Engine *e = t.engine;
LuaType<Engine *>::pushdata(L, e);
lua_setfield(L, -2, "engine");
LuaType<const string &>::pushdata(L, t.name_space);
lua_setfield(L, -2, "name_space");
*env = LuaObj::todata(L, -1);
lua_pop(L, 1);
lua_getglobal(L, t.klass.c_str());
// ----------code 1 ok -----------------
if (lua_type(L, -1) == LUA_TNIL){
lua_pop(L,1);
string do_str= t.klass + "=require(\"" + t.klass + "\")";
luaL_dostring(L, do_str.c_str()); // t.klass = require(' tklass')
lua_getglobal(L, t.klass.c_str());
LOG(ERROR) << "-------->reload module "<< luaL_typename(L, -1);
}
// ---------------------------------------------------------
// -------------------code 2
if (lua_type(L, -1) == LUA_TNIL){
lua_pop(L,1);
luaL_requiref(L, t.klass.c_str() , 0 , -1);
lua_getglobal(L, t.klass.c_str());
LOG(ERROR) << "-------->reload module "<< luaL_typename(L, -1);
// ---------------------------------------------------------------------
if (lua_type(L, -1) == LUA_TTABLE) {
lua_getfield(L, -1, "init");
if (lua_type(L, -1) == LUA_TFUNCTION) {
LuaObj::pushdata(L, *env);
int status = lua_pcall(L, 1, 1, 0);
if (status != LUA_OK) {
const char *e = lua_tostring(L, -1);
LOG(ERROR) << "Lua Compoment of " << t.name_space << " initialize error:(" << status << "): " << e;
}
}
luaL_requiref void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb); If package.loaded[modname] is not true, calls the function openf with the string modname as an argument and sets the call result to package.loaded[modname], as if that function has been called through require.
If glb is true, also stores the module into the global modname.
Leaves a copy of the module on the stack.