【问题标题】:Lua emulating the require functionLua 模拟 require 函数
【发布时间】:2016-04-26 17:31:11
【问题描述】:

在嵌入式 lua 环境(魔兽世界 - 魔兽世界)中缺少 require 函数。

我想要移植一个现有的 lua 源代码 (an great OO-library) 以便在 WoW 中使用它。库本身相对较小(大约 8 个小文件),但当然它大量使用 require。

魔兽世界通过在 XML 文件中定义来加载文件和库,例如:

<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
    <Script file="LibOne.lua"/>
    <Script file="LibTwo.lua"/>
</Ui>

但我不知道魔兽世界中低级库操作是如何完成的。

《魔兽世界》中的 AFAIK 甚至连 package. 表也不见了。 :(

所以问题:对我来说,简化的方法是编写一个函数,该函数将使用 WoW 中可用的接口模拟 require 函数。问题是如何。谁能给我一些指示?

或者作为替代方案,为了将提到的现有源移植到 WoW,我需要将 lua 源中的 require Some.Other.Module 行替换为 WoW 可以理解的内容。在 WoW 中,这样的require Some.Module 的等价物/替代品是什么?

魔兽世界如何处理低级别的模块/库?

【问题讨论】:

    标签: lua world-of-warcraft


    【解决方案1】:

    您可以使用各种合并脚本之一将所有文件合并为一个,例如amalg。然后,您可以使用通常的 WoW 方式加载此文件和实现 require 函数的存根:

    <Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
        <Script file="RequireStub.lua"/>
        <Script file="AllModules.lua"/><!-- amalgamated Lua modules -->
        <Script file="YourCode.lua"/>
    </Ui>
    

    文件RequireStub.lua 可能如下所示:

    package = {}
    local preload, loaded = {}, {
      string = string,
      debug = debug,
      package = package,
      _G = _G,
      io = io,
      os = os,
      table = table,
      math = math,
      coroutine = coroutine,
    }
    package.preload, package.loaded = preload, loaded
    
    
    function require( mod )
      if not loaded[ mod ] then
        local f = preload[ mod ]
        if f == nil then
          error( "module '"..mod..[[' not found:
           no field package.preload[']]..mod.."']", 1 )
        end
        local v = f( mod )
        if v ~= nil then
          loaded[ mod ] = v
        elseif loaded[ mod ] == nil then
          loaded[ mod ] = true
        end
      end
      return loaded[ mod ]
    end
    

    这应该模拟足够多的package 库,以便为您提供一个可以在合并文件中加载模块的工作require。不过,不同的合并脚本可能需要来自 package 的不同位,因此您可能需要查看生成的 Lua 源代码。

    在 Coat 的特定情况下,您可能还需要为其他 Lua 函数实现存根。例如。我看到Coat 使用debug 库...

    【讨论】:

    • 这段代码对我来说真的很难理解。 loaded 中所有这些变量的目的是什么?你能说得更详细些吗?
    • @Hatefiend: package.loaded 缓存所有加载/需要的模块。上面列出的是 Lua 标准库中的模块。在“普通”Lua 中,它们可以通过 require 和 package.loaded 获得,也可以作为全局变量使用。在魔兽世界中只有全局变量,所以我们必须自己填写package.loaded。
    【解决方案2】:

    WoW 环境根本没有dofile 或任何其他读取外部文件的方法。您需要明确提及必须在.toc 文件或.xml 中从.toc 引用的所有文件。

    然后您可以编写自己的require 实现以保持与您的库的兼容性,这将非常简单,因为它只需要解析模块名称并从modules.loaded 表中检索它的内容,但您仍然会需要更改原始源以使文件在该表中注册,并且您需要手动将所有文件排列成正确的加载顺序。

    或者,您可以将文件重新排列到单独的 WoW 插件中,并使用其自己的内置 Dependencies/OptionalDeps 设施或流行的 LibStub 框架来自动处理加载顺序。

    【讨论】:

    • 那么,modules.loaded 表可用吗?因为缺少package.* 表(AFAIK - 它由“标准”lua 中的require 使用)。
    • 不,不是。但这只是一张普通的桌子。使用它只是require 框架的约定。您可以自己制作和填充。
    • 魔兽环境有loadstring吗?
    • @EgorSkriptunoff:它seems that way。
    • 是的,但它被修补为只允许纯源代码而不是字节码。
    猜你喜欢
    • 2014-06-11
    • 2015-11-10
    • 2012-08-05
    • 1970-01-01
    • 2017-08-28
    • 2012-03-17
    • 2011-08-22
    • 2017-08-01
    • 2017-01-15
    相关资源
    最近更新 更多