【问题标题】:Attempt to call global 'this' (a nil value)尝试调用全局“this”(零值)
【发布时间】:2020-10-20 10:52:38
【问题描述】:

我可以看到有人问过类似的问题,但是我对 lua 编码并不是很熟悉。 我正在尝试修复一个旧的魔兽世界香草插件,以便在经典客户端中运行。

代码如下:

    function FHH_OnLoad()

    this:RegisterEvent("PLAYER_ENTERING_WORLD");
    this:RegisterEvent("UPDATE_MOUSEOVER_UNIT");

    -- Register Slash Commands
    SLASH_FHH1 = "/huntershelper";
    SLASH_FHH2 = "/hh";
    SlashCmdList["FHH"] = function(msg)
        FHH_ChatCommandHandler(msg);
    end
    
    local version = GetAddOnMetadata("GFW_HuntersHelper", "Version");
    GFWUtils.Print("Fizzwidget Hunter's Helper "..version.." initialized!");
    
end

它会抛出以下错误;

Message: Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: attempt to index global 'this' (a nil value)
Time: Tue Jun 30 09:25:14 2020
Count: 1
Stack: Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: attempt to index global 'this' (a nil value)
Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: in function `FHH_OnLoad'
[string "*:OnLoad"]:1: in function <[string "*:OnLoad"]:1>

Locals: (*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = "attempt to index global 'this' (a nil value)"

我尝试过使用“this”语句,但我不确定该怎么做,我想看看你们这里的聪明人是否知道发生了什么

【问题讨论】:

  • “框架”,如 WoW 附加组件框架通常会给语言带来新的味道,所以我的评论可能对你的情况有误。 Lua 中对当前对象的引用称为self。当您使用: 而不是. 调用函数时,您调用此函数的对象将作为第一个参数隐式传递。如果将函数定义为something:yourfunction() 而不是something.yourfunction(),则第一个参数隐式命名为self。函数定义function something:yourfunction() [...] end等于function something.yourfunction(self) [...] end
  • 那么27 会在你的脚本中出现什么?
  • 第27行是onload; this:RegisterEvent("PLAYER_ENTERING_WORLD");我想下一行也是一样的,因为它是一个相同的函数
  • 这真的取决于正在发生的事情以及原始开发人员采取的方法。在过去的某个时候,Blizz 从各种全局变量转移到了局部变量。检查 FHH_OnLoad 的实际使用位置(名称表明它位于 XML 中的某个位置)。 &lt;OnLoad&gt; 将单个参数 self 传递给其内容,然后可以将其传递给 FHH_OnLoad
  • 你是对的,它在一个 XML 文件中。我想我可能已经吃得太饱了,我是一个爱好 C# 编码器,并认为我可以通过修复这个插件来寻找我的方式,但看起来它比我预期的要复杂。 @green 虽然你是对的,但 FHH_OnLoad 存在于 xml 中,只是没有参数; &lt;Frame name="HuntersHelperFrame"&gt; &lt;Scripts&gt; &lt;OnLoad&gt; FHH_OnLoad(); &lt;/OnLoad&gt; &lt;OnEvent&gt; FHH_OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); &lt;/OnEvent&gt; &lt;/Scripts&gt; &lt;/Frame&gt;

标签: lua add-on world-of-warcraft


【解决方案1】:

如果所讨论的插件已经很老了,那么在过去的某个时间点(2010 年?),插件 API 已经从全局变量转移到了局部变量。

框架是在 XML 文件中定义的,就像您在评论中发布的那样:

<Frame name="HuntersHelperFrame">
   <Scripts>
      <OnLoad>FHH_OnLoad();</OnLoad>
      <OnEvent>
         FHH_OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); 
      </OnEvent>
   </Scripts>
</Frame>

&lt;Scripts&gt; 中的元素实际上被称为函数,其内容为函数体。它们使用 一些 参数调用。您可以使用 World of Warcraft API 作为参考找出 what 参数。它不是官方的,但它是最接近参考手册的东西。

目前,您对Widget handlers感兴趣。

那么,您应该采取的第一步是:

  1. 更改 XML:
    <Frame name="HuntersHelperFrame">
       <Scripts>
          <OnLoad>FHH_OnLoad(self)</OnLoad>
          <OnEvent>
             FHH_OnEvent(self, event, ...) 
          </OnEvent>
       </Scripts>
    </Frame>
    
  2. 更改 lua 以反映:
    function FHH_OnLoad(self)
       self:RegisterEvent("PLAYER_ENTERING_WORLD")
       -- and so on, change all occurrences of `this` to `self`
       -- or simply name the first argument `this` instead of `self`:
       -- function FHH_OnLoad(this)
    end
    
    -- Change all of the functions:
    function FHH_OnEvent(self, event, ...)
       -- function body
    end
    

根据插件的大小,它可能会成为一大块工作。可悲的是,这还没有结束。请小心,因为脚本可能直接依赖全局变量的存在并执行一些技巧。

我想您可以尝试使用 local this = self 之类的技巧来解决它,但这可能不适用于所有情况,并且由于框架解析 XML 的方式可能会导致一些问题。

最后一点;多年来,API 发生了很大变化,您很可能会遇到更多问题。祝你好运!

【讨论】:

  • 非常感谢。根据您的提示,我能够使插件正常工作。非常感激!没有更多错误,现在我需要弄清楚为什么它没有将能力打印到工具提示中:)
猜你喜欢
  • 2019-09-06
  • 2013-03-28
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 2020-03-08
  • 2013-09-04
  • 1970-01-01
相关资源
最近更新 更多