librime-lua icon indicating copy to clipboard operation
librime-lua copied to clipboard

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

Open shewer opened this issue 3 years ago • 4 comments

可省去 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 avatar Jan 17 '22 10:01 shewer

用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
             

shewer avatar Jan 22 '22 00:01 shewer

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

hchunhui avatar Feb 06 '22 03:02 hchunhui

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

hchunhui avatar Feb 06 '22 03:02 hchunhui

我剛才用 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)

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.

shewer avatar Feb 06 '22 04:02 shewer