在嵌入式(在 VLC 中)的 Lua 中尝试调用全局的“tonumber”(一个空值),出现错误“尝试调用全局'tonumber'(空值)”。

我在Ubuntu 11.04上使用VLC媒体播放器1.1.9。 我尝试使用VLC的lua扩展进行实验; 所以我在~/.local/share/vlc/lua/extensions/中添加了一个名为test.lua的文件,其中只有这两行:

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](http://www.lua.org/manual/5.1/manual.html#pdf-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扩展中正确使用它(和其他)标准函数?

点赞
用户2002452
用户2002452

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

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

1 / "25.000"

这个字符串将被强制转换为数字。

或者,你可以定义一个类似 tonumber 的函数:

string_to_num = function(s) return s + 0 end

这又依赖于动态类型。

2015-01-24 14:13:28
用户234175
用户234175

文档对于 VLC Lua 扩展来说非常稀少,但我在 Github 的 VLC 库中找到了一个例子,链接在此处:https://github.com/videolan/vlc/blob/master/share/lua/extensions/VLSub.lua

根据这个例子,似乎你需要为 VLC 提供一些基本的事件函数,当某些事件发生时,VLC 才会调用这些函数。我注意到一些显而易见的回调处理程序:

  • descriptor,需要返回一个包含描述你的插件的字段的表格。
  • activate,当你从 视图 菜单栏激活它时似乎会被调用。
  • deactivate,当你从 视图 菜单栏停用插件时被调用。

还有另外一些函数,比如 closeinput_change,你可以猜测它们的作用。

在我的短暂测试中,我使用 Win7 下的 VLC 2.0.8,看起来 VLC 使用空的沙箱环境加载 Lua 扩展。这可能是你在全局范围内尝试进行计算时会得到 nil 的原因,我敢打赌其它标准的 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

2015-01-25 09:04:13