Lua模拟require函数

时间:2016-04-26 17:31:12

标签: lua world-of-warcraft

在嵌入式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>

但我不知道如何在WoW中完成低级库操作。

魔兽世界中的AFAIK甚至也缺少package.表格。 :(

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

或者作为替代方案,为了将提到的现有源移植到WoW,我需要将lua源中的require Some.Other.Module行替换为WoW将理解的内容。魔兽世界中require Some.Module的等同/替代是什么?

WoW如何处理低级别的模块/库?

2 个答案:

答案 0 :(得分:4)

您可以使用各种合并脚本之一将所有文件合并为一个文件,例如: 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库...

答案 1 :(得分:3)

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

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

或者,您可以将文件重新排列到单独的WoW-addons中,并使用其自己的内置modules.loaded / Dependencies工具或热门LibStub框架来自动处理加载顺序。