"试图打电话给全球' tonumber' (零值)"在Lua,嵌入式(在VLC中)

时间:2015-01-24 05:43:11

标签: lua vlc

我在Ubuntu 11.04上使用VLC媒体播放器1.1.9。我正在尝试为VLC试用lua个扩展程序;所以我在test.lua中添加了文件~/.local/share/vlc/lua/extensions/,其中只包含以下两行:

fps="25.000"
frame_duration=1/tonumber(fps)

当我使用详细输出运行vlc进行调试时,我得到(编辑为多行分割:):

$ vlc --verbose 2
...
[0xa213874] lua generic warning: Error loading script 
 ~/.local/share/vlc/lua/extensions/test.lua: 
 .../.local/share/vlc/lua/extensions/test.lua:2:
  attempt to call global 'tonumber' (a nil value)
...

现在,据我所知,tonumber作为函数是Lua5.1本身(Lua 5.1 Reference Manual: tonumber)的一部分 - 并且在我的系统上:

$ locate --regex 'lua.*so.*' | head -4
/usr/lib/libipelua.so.7.0.10
/usr/lib/liblua5.1.so
/usr/lib/liblua5.1.so.0
/usr/lib/liblua5.1.so.0.0.0

......显然我确实安装了Lua 5.1。

那么,为什么我在这里使用tonumber会出错?我如何在VLC lua扩展中正确使用这个(和其他)标准函数?

2 个答案:

答案 0 :(得分:2)

VLC Lua扩展的文档很少,但至少我在github vlc存储库中找到了一个示例:https://github.com/videolan/vlc/blob/master/share/lua/extensions/VLSub.lua

从该示例来看,似乎您需要为您的插件提供一些基本事件功能,以便VLC在发生某些事件时调用。我注意到一些明显的回调处理程序:

  • descriptor,这应该返回一个包含描述你的插件的字段的表。
  • activate,当您从view菜单栏中激活它时,似乎会调用它。
  • deactivate,当您从view菜单栏停用插件时调用。

加上其他一些功能,例如closeinput_change,您可以猜出它们的用途。

根据我在Win7下对VLC 2.0.8进行的简短测试,看来VLC使用空的沙箱环境加载lua扩展。这可能是您nil获得tonumber的原因,我打赌当您尝试在此全局范围内执行计算时,其他任何标准lua函数都不可访问。

但是,如果我将该代码移动到其中一个事件处理函数中,则可以再次访问所有这些标准函数。例如:

function descriptor()
   return
   {
      title = "Test Ext";
      version = "0.1";
      author = "";
      shortdesc = "Testing Lua Extension";
      capabilities = {};
      description = "VLC Hello Test Addon";
   }
end

function activate()
  print "test activating"

  local fps = tonumber "25.000"
  local frame_duration = 1 / fps
  print(frame_duration)

  return true
end
-- ...

打印出您在控制台调试日志中所期望的内容。现在文档(它没有什么)没有提到任何这些,但是这里可能发生的是VLC在调用任何这些事件处理程序时将标准lua函数和vlc api表注入沙盒环境。但是在扩展加载阶段,它是在一个空的沙箱环境中完成的,这解释了为什么当你尝试在大多数范围内使用它时,所有这些lua函数调用最终都是nil

我建议从github克隆VLC源代码树,然后在嵌入lua的C源上执行grep,看看VLC在幕后真正做了什么。大多数相关代码可能会在这里:https://github.com/videolan/vlc/tree/master/modules/lua

答案 1 :(得分:1)

系统中安装的某些扩展脚本可能会覆盖该函数,并且Lua解释器实例在所有扩展脚本之间共享,因此如果在您之前调用该脚本,则最终无法调用该函数。

作为一种快速解决方法,Lua是动态类型的,您仍然可以执行以下操作:

1 / "25.000"

并且字符串将被强制转换为数字。

或者,您可以定义tonumber等效内容,如:

string_to_num = function(s) return s + 0 end

这再次依赖于动态类型。