[英]Lua 5.2 C API and require
I want to call a Lua script which require()
s lyaml
module, Lua binding for LibYAML, from a C program. 我想从一个C程序调用一个Lua脚本,该脚本
require()
s lyaml
模块,Lua绑定LibYAML。
I compiled Lua 5.2 from source and I hacked the module to make it work with Lua 5.2. 我从源代码编译了Lua 5.2,并且我修改了模块以使它与Lua 5.2一起工作。 It can be found on github .
它可以在github上找到。
The Lua script follows, it works either with Lua 5.1 and 5.2: Lua脚本如下,它适用于Lua 5.1和5.2:
-- foo.lua
require('lyaml')
function hello ()
res = lyaml.load("a: 4\n")
return res.a
end
-- then calling hello() it works like a charm
print( hello() ) -> 4
I wrote a C program which should call hello()
from the script, following Programming in Lua, Chapter 25 and Lua 5.2 Reference Manual . 我写了一个C程序,应该按照Lua编程,第25章和 Lua 5.2参考手册从脚本中调用
hello()
。
The C program follows: C程序如下:
/* foo.c */
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int main(void)
{
double z;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if (luaL_dofile(L, "foo.lua"))
luaL_error(L, "error running script: %s", lua_tostring(L, -1));
lua_getglobal(L, "hello");
if (lua_pcall(L, 0, 1, 0) != 0)
luaL_error(L, "error calling hello: %s", lua_tostring(L, -1));
if (!lua_isnumber(L, -1))
luaL_error(L, "result must be number");
z = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_close(L);
return 0;
}
I compile issuing: 我编译发行:
gcc -Wall -o foo foo.c -ldl -lm -llua
Then when running foo
, I receive at runtime the following error: 然后在运行
foo
,我在运行时收到以下错误:
PANIC: unprotected error in call tu Lua API (
error running script: error loading module 'lyaml' from file '/path/to/lyaml.so':
/path/to/lyaml.so: undefined symbol: lua_gettop)
Aborted
So I tried to load lyaml
from the C program, adding the following line after luaL_openlibs()
call: 所以我尝试从C程序加载
lyaml
,在luaL_openlibs()
调用后添加以下行:
luaL_requiref(L, "lyaml", luaopen_package, 1);
After recompilation the error becomes: 重新编译后,错误变为:
PANIC: unprotected error in call tu Lua API (
error running script:
hello.lua:4: attempt to index global 'lyaml' (a nil value))
Aborted
So I imagine that there's no lyaml
symbol and the require()
call fails somehow. 所以我想,没有
lyaml
符号,并且require()
调用以某种方式失败。
By reading luaL_requiref()
documentation I thought modname
would be set by its call setting glb
flag to true: 通过阅读
luaL_requiref()
文档,我认为modname
将通过其调用设置glb
标志设置为true:
void luaL_requiref (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
Calls function
openf
with stringmodname
as an argument and sets the call result inpackage.loaded[modname]
, as if that function has been called throughrequire
.调用函数
openf
并将字符串modname
作为参数,并在package.loaded[modname]
设置调用结果,就好像该函数已通过require
调用一样。
If glb is true, also stores the result into globalmodname
.如果glb为true,则还将结果存储到全局
modname
。
Leaves a copy of that result on the stack.将该结果的副本留在堆栈上。
I tried to comment the require()
call in Lua script and the result is the same. 我试图在Lua脚本中注释
require()
调用,结果是一样的。
What did I do wrong? 我做错了什么? Am I forgetting to do something?
我忘了做某事吗?
I hacked the module updating deprecated (removed) functions/types with their substitute as follows: 我用其替代品破解了模块更新已弃用(已删除)的函数/类型,如下所示:
lua_strlen() -> luaL_len()
luaL_reg -> luaL_Reg
luaL_getn() -> luaL_len()
However Lua scripts using lyaml
work so I think the problem is not my hack. 然而Lua脚本使用
lyaml
工作所以我认为问题不是我的黑客。
I tried original lyaml
module with Lua 5.1. 我用Lua 5.1尝试了原始的
lyaml
模块。 Results are the same, so I'm sure the problem is not my hack. 结果是一样的,所以我确定问题不是我的黑客。
Adding the following line, as suggested by Doug Currie in his answer, the C program works perfectly with Lua 5.1. 根据Doug Currie的回答,添加以下行,C程序与Lua 5.1完美配合。 I still get the same error in 5.2 though.
我仍然在5.2中得到相同的错误。
lyaml = require('lyaml')
foo.lua
as written will only run in Lua 5.1.x -- your hacked lyaml.c
doesn't set the global lyaml
and neither does require in Lua 5.2. 写的
foo.lua
只能在Lua 5.1.x中运行 - 你被黑的lyaml.c
没有设置全局lyaml
,在Lua 5.2中也没有要求。 I suspect your PATH did not have Lua 5.2 when you ran the first test "works like a charm," or else you set lyaml
manually before you loaded foo.lua
. 我怀疑你的PATH没有Lua的5.2当您运行第一次测试“的作品就像一个魅力,”否则你设置
lyaml
手动你加载之前foo.lua
。
foo.lua
should start with foo.lua
应该从
lyaml = require('lyaml')
I solved... the root of all problems was a bad use of luaL_requiref()
. 我解决了......所有问题的根源都是对
luaL_requiref()
的错误使用。
Reading this thread i got inspired by this follow up: 阅读这篇帖子我得到了这个后续的启发:
In Lua 5.2, libraries no longer create globals;
在Lua 5.2中,库不再创建全局变量; they just return the library table.
他们只是返回图书馆表。
luaL_openlibs
callsluaL_requiref
instead of callingluaopen_*
, andluaL_requiref
sets the corresponding globals.luaL_openlibs
调用luaL_requiref
而不是调用luaopen_*
,而luaL_requiref
设置相应的全局变量。
so it is necessary to call luaL_requiref()
to load the module and set the lyaml
global. 所以有必要调用
luaL_requiref()
来加载模块并设置lyaml
全局。
As stated in the question I tried using 正如我尝试使用的问题中所述
luaL_requiref(L, "lyaml", luaopen_package, 1);
but it's totally wrong because luaopen_package()
is the loader function for Lua standard package
module... I had to use instead: 但这是完全错误的,因为
luaopen_package()
是Lua标准package
模块的加载器函数...我不得不使用:
luaL_requiref(L, "lyaml", luaopen_lyaml, 1);
and compile with 并编译
gcc -L/path/to/5.2 -Wall -o foo foo.c -ldl -lm -llua -l:lyaml.so.1
to get references to luaopen_lyaml()
. 获取对
luaopen_lyaml()
引用。
In Lua 5.1, as Doug Currie said, it was enough to issue 在Lua 5.1中,正如Doug Currie所说,它足以发布
lyaml = require('lyaml')
in hello.lua
, without calling luaL_requiref()
in C program. 在
hello.lua
,不在C程序中调用luaL_requiref()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.