Lua C 函数调用 returns 无
Lua C function call returns 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 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 ?
luaL_setfuncs 只是将您的函数注册到 table 中。
改为使用 luaL_newlib
。它会创建一个新的 table 并在那里注册您的函数。然后你需要将 table 压入 lua 堆栈。
luaL_newlib (L, foo);
return 1;
至于导致错误的原因,lua_setglobal
从堆栈中弹出库 table,因此 luaopen_foo
不会 return 它。然后(虽然我不明白为什么) require "foo"
returns 库的文件路径(字符串)代替,字段 ("foo_filepath").bar
是 nil
.
因此,删除对 lua_setglobal
的调用可以解决问题,即使您没有按照 Ravi 的建议使用 library-creating 宏 luaL_newlib
。
要将库 table 设置为全局 foo
和 return 它来自 require
,您必须推送一个在执行 lua_setglobal(L, "foo")
之前,将 table 的第二个副本与 lua_pushvalue(L, -1)
一起放入堆栈,留下 table 的原始副本由 luaopen_foo
编辑 return ].
我为 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 ?
luaL_setfuncs 只是将您的函数注册到 table 中。
改为使用 luaL_newlib
。它会创建一个新的 table 并在那里注册您的函数。然后你需要将 table 压入 lua 堆栈。
luaL_newlib (L, foo);
return 1;
至于导致错误的原因,lua_setglobal
从堆栈中弹出库 table,因此 luaopen_foo
不会 return 它。然后(虽然我不明白为什么) require "foo"
returns 库的文件路径(字符串)代替,字段 ("foo_filepath").bar
是 nil
.
因此,删除对 lua_setglobal
的调用可以解决问题,即使您没有按照 Ravi 的建议使用 library-creating 宏 luaL_newlib
。
要将库 table 设置为全局 foo
和 return 它来自 require
,您必须推送一个在执行 lua_setglobal(L, "foo")
之前,将 table 的第二个副本与 lua_pushvalue(L, -1)
一起放入堆栈,留下 table 的原始副本由 luaopen_foo
编辑 return ].