Lua C函数调用返回nil

时间:2018-04-06 09:40:07

标签: c lua luac lua-5.3

我为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  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> local foo = require "foo"
> local res = foo.bar(3.0, 6.0)
> res
nil

不会抛出错误,因为我在返回值之前能够printf C代码中的结果,我知道代码被调用并且结果计算成功。

有什么想法吗?

Edit1:通过不使用局部变量,我获得了这个堆栈跟踪而不是nil值:

root@d7340c919be4:/# lua5.3
Lua 5.3.3  Copyright (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 ?

2 个答案:

答案 0 :(得分:3)

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

相反,请使用luaL_newlib。它创建一个新表并在那里注册您的函数。然后你需要将表推到lua堆栈。

luaL_newlib (L, foo);
return 1;

答案 1 :(得分:1)

至于导致错误的原因,lua_setglobal从堆栈中弹出库表,以便luaopen_foo不返回它。然后(虽然我不明白为什么)require "foo"改为返回库的文件路径(字符串),字段("foo_filepath").barnil

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

要将库表设置为全局foo 并且require返回它,您必须将表的第二个副本推送到具有{{1}的堆栈在执行lua_pushvalue(L, -1)之前,保留lua_setglobal(L, "foo")返回的表的原始副本。