简体   繁体   English

Lua C函数调用返回nil

[英]Lua C function call returns nil

I wrote a simple C plugin for Lua: 我为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;
}

The code is compiled successfully with this GCC command: 使用此GCC命令成功编译了代码:

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

In a Lua 5.3 REPL, I'm able to find and import the module successfully as well, but the returned value of the function call is always nil : 在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

No errors are thrown and since I'm able to printf the result in the C code before returning the value, I know the code is called and the result calculated successfully. 没有错误被抛出,并且由于我能够在返回值之前在C代码中printf结果,因此我知道代码已被调用并且结果计算成功。

Any ideas? 有任何想法吗?

Edit1: By not using local variables I get this stack trace instead of a nil value: 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 ?

luaL_setfuncs just registers your functions into a table. luaL_setfuncs只是将您的函数注册到表中。

Instead, use luaL_newlib . 而是使用luaL_newlib It creates a new table and registers your functions there. 它创建一个新表并在那里注册您的函数。 Then you need to push the table on to lua stack. 然后,您需要将桌子推入lua堆栈。

luaL_newlib (L, foo);
return 1;

As to what's causing the error, lua_setglobal pops the library table from the stack, so that luaopen_foo does not return it. 至于导致错误的原因, lua_setglobal从堆栈中弹出库表,因此luaopen_foo不会返回它。 Then (though I don't understand why) require "foo" returns the file path of the library (a string) instead, and the field ("foo_filepath").bar is nil . 然后(尽管我不明白为什么) require "foo"返回库的文件路径(字符串),而字段("foo_filepath").barnil

So, removing the call to lua_setglobal fixes the problem, even if you do not use the library-creating macro luaL_newlib as Ravi recommends. 因此,即使不按照Ravi的建议使用创建库的宏luaL_newlib ,删除对lua_setglobal的调用也可以解决该问题。

To set the library table as global foo and return it from require , you have to push a second copy of the table to the stack with lua_pushvalue(L, -1) before doing lua_setglobal(L, "foo") , leaving the original copy of the table to be returned by luaopen_foo . 要将库表设置为全局foo require返回它,您必须先使用lua_pushvalue(L, -1)将表的第二个副本推入堆栈,然后再执行lua_setglobal(L, "foo") ,保留原始副本luaopen_foo返回的luaopen_foo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM