hchunhui / librime-lua

Extending RIME with Lua scripts
BSD 3-Clause "New" or "Revised" License
304 stars 43 forks source link

lua_component 自載程式 require('klass.c_str() ) C_API ?? #156

Open shewer opened 2 years ago

shewer commented 2 years ago

可省去 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())
}    
shewer commented 2 years ago

用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
hchunhui commented 2 years ago

原本的设计是不强求 lua_component 必定对应一个可以被 require 的文件,而是对应一个 global function(或者 table)就可以。这样相比 require 自载可以理灵活,比如简单的 component 全部写到 rime.lua 就可以了;有些复杂的功能需要在一个文件里面写多个 component 。这两种情况自载都不容易做到。

hchunhui commented 2 years ago

不过这个想法很合理:需要有某种办法能自动地载入他人做好的功能模块,而不是要用户自己编辑 rime.lua,类似 #151 的要求。

shewer commented 2 years ago

我剛才用 luaL_dostring() ok,前提是 klass 要和 moduel 同名

151 是要 lua 初始化lua_state 時載入路逕下的所有檔案

這是在 create lua_component時發現 找不到 _G[klass]

.custom.yaml patch: engine/translators/lua_translator@date 載入成功 用 luaL_requiref(L, t.klass, nullptr, -1) 會發生 segmentation fault (core dumped) ```c++ static void raw_init(lua_State *L, const Ticket &t, an *env, an *func, an *fini) { lua_newtable(L); Engine *e = t.engine; LuaType::pushdata(L, e); lua_setfield(L, -2, "engine"); LuaType::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_[require](http://www.lua.org/manual/5.4/manual.html#pdf-require)f (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.