Lua C函数调用返回nil

我为Lua写了一个简单的C插件:

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static int bar (lua_State *L) {
  double arg1 = luaL_checknumber(L, 1);
  double arg2 = luaL_checknumber(L, 2);
  lua_Number res = arg1 + arg2;
  lua_pushnumber(L, res);
  return 1;
}

int luaopen_foo (lua_State *L) {
  static const struct luaL_Reg foo [] = {
    {"bar", bar},
    {NULL, NULL}
  };
  lua_newtable(L);
  luaL_setfuncs(L, foo, 0);
  lua_setglobal(L, "foo");
  return 1;
}

使用以下GCC命令成功编译代码:

gcc -W -Wall -g -fPIC -shared -I/usr/include/lua5.3 -o foobar.so foobar.c

在Lua 5.3 REPL中,我也能够成功地找到并导入模块,但函数调用返回的值始终为nil

root@b1898c1cc270:/# lua5.3
Lua 5.3.3  版权所有 (C) 1994-2016 Lua.org, PUC-Rio
> local foo = require "foo"
> local res = foo.bar(3.0, 6.0)
> res
nil

没有抛出错误,并且由于我在返回值之前能够printf函数计算的结果,我知道代码是被调用并且结果成功计算的。

有什么想法吗?

编辑1:如果不使用本地变量,我会得到以下堆栈跟踪而不是nil值:

root@d7340c919be4:/# lua5.3
Lua 5.3.3  版权所有 (C) 1994-2016 Lua.org, PUC-Rio
> foo = require "foo"
> res = foo.bar(3.0, 6.0)
stdin:1: attempt to call a nil value (field 'bar')
stack traceback:
    stdin:1: in main chunk
    [C]: in ?
点赞
用户3572445
用户3572445

luaL_setfuncs 只是将您的函数注册到一个表中。

相反,使用 luaL_newlib。它会创建一个新表并在其中注册您的函数。然后您需要将该表推入到 lua 栈中。

luaL_newlib (L, foo);
return 1;
2018-04-06 10:46:46
用户9383219
用户9383219

关于错误的原因,lua_setglobal 会从栈中弹出库表,以至于 luaopen_foo 不会返回该表。然后(虽然我不明白为什么) require "foo" 会返回库的文件路径(字符串),而字段 ("foo_filepath").bar 则为 nil

因此,即使您不使用 Ravi 推荐的创建库的宏 luaL_newlib,删除对 lua_setglobal 的调用也可以解决问题。

要将库表设置为全局变量 foo require 中返回它,您需要使用 lua_pushvalue(L, -1) 将库表的第二个副本推到堆栈中,然后执行 lua_setglobal(L, "foo"),从而留下原始的库表供 luaopen_foo 返回。

2018-04-06 21:02:26