【问题标题】:lua - Using two same name function from different lua liblua - 使用来自不同 lua 库的两个同名函数
【发布时间】:2015-11-18 06:06:33
【问题描述】:

我有两个由 lua 编写的不同库,但函数名相同。

如何在不修改库源的情况下选择其中之一?

require ('A') --A lib
require ('B') --B lib
test() -- function from B

如果我想要 A 的测试功能,我该怎么做?

这是我尝试过的一些方法。

  1. LuaJ loading two functions with the same name from two different LuaScripts

    我找到了这个,但我不想修改 lib 源代码。

  2. 将函数另存为不同的名称,如下所示:

    require ('A') --A lib
    _G.testA = test
    require ('B') --B lib
    _G.testB = test
    
    testA() -- function from A
    testB() -- function from B
    

    但如果有一天一个新的函数名称 testA() 或 testB() 会再次中断。

    而且我仍然需要将所有存在的 test() 更改为 testA() 或 testB()。

    有没有更好的办法?

【问题讨论】:

  • “修改lib源代码”是“更好的方法”。
  • 理想情况下,您使用的库不会污染全局命名空间,但如果它们污染了,您可以编写一些对环境进行差异化并将库的全局状态移动到范围内的东西。
  • @Mud 你能给我看一些示例代码吗?

标签: lua


【解决方案1】:

你描述的代码

require ('A') --A lib
_G.testA = test
require ('B') --B lib
_G.testB = test

testA() -- function from A
testB() -- function from B

绝对是解决问题的一种方法。

为避免将来出现问题,您可以将新功能放入地图中

-- Example library.lua

-- Old code not in map
function my_old_func(params)
    -- do some stuff
end

-- New code goes down here
local mylibrary = {}
function mylibrary:my_awesome_func(params)
    my_old_func(params)
end

【讨论】:

    【解决方案2】:

    这正是 Lua 模块 shouldn't set global variables 的原因,而是将其所有函数/变量导出到通过 require 返回的表中。

    但是,如果您的两个模块是 Lua 模块,您可以为每个模块设置自定义环境,以便模块定义的全局变量在单独的表中结束:

    #!/usr/bin/lua
    
    -- fallback implementation of package.searchpath for Lua 5.1
    local searchpath = package.searchpath
    -- not necessary if you have Lua 5.2+:
    if not searchpath then
      local delim = package.config:match( "^(.-)\n" ):gsub( "%%", "%%%%" )
    
      function searchpath( name, path )
        local pname = name:gsub( "%.", delim ):gsub( "%%", "%%%%" )
        local msg = {}
        for subpath in path:gmatch( "[^;]+" ) do
          local fpath = subpath:gsub( "%?", pname )
          local f = io.open( fpath, "r" )
          if f then
            f:close()
            return fpath
          end
          msg[ #msg+1 ] = "\n\tnofile '"..fpath.."'"
        end
        return nil, table.concat( msg )
      end
    end
    
    
    -- table for storing the environments for each module
    local environments = {}
    
    
    -- clone of the standard Lua searcher which sets a custom environment
    -- for the loaded chunk and stores it in the environments table.
    local function my_lua_searcher( modname )
      local fpath, msg = searchpath( modname, package.path )
      if not fpath then
        return msg
      end
      local env = setmetatable( {}, { __index = _G } )
      env._G = env
      environments[ modname ] = env
      local f = assert( loadfile( fpath, nil, env ) )
      if setfenv then -- for Lua 5.1
        setfenv( f, env )
      end
      return f, fpath
    end
    
    
    -- replace the Lua searcher (at index 2)
    local searchers = package.searchers or package.loaders
    -- if someone added to package.searchers, we have no way of knowing
    -- which function is the Lua searcher we want to replace:
    assert( #searchers == 4, "package.searchers has been modified" )
    searchers[ 2 ] = my_lua_searcher
    
    
    -- test it:
    require( "A" )
    require( "B" )
    environments[ "A" ].test()
    environments[ "B" ].test()
    

    【讨论】:

      猜你喜欢
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 2017-04-16
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      相关资源
      最近更新 更多