2012-07-14 79 views
5

问题

我要调用一个Lua脚本require()小号lyaml模块,Lua若LibYAML结合,从C程序。的Lua 5.2 C API和需要

我从源代码编译Lua 5.2,我砍了模块,使其与Lua 5.2一起工作。它可以在github找到。

的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 


问题

我写了一个C程序,它应该叫hello()从剧本,以下Programming in Lua, Chapter 25Lua 5.2 Reference Manual

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; 
} 

我编译发行:

gcc -Wall -o foo foo.c -ldl -lm -llua 
运行 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 

所以,我想从C程序加载lyaml,在0之后添加以下行电话:

luaL_requiref(L, "lyaml", luaopen_package, 1); 

重新编译后的误差变:

PANIC: unprotected error in call tu Lua API (
    error running script: 
     hello.lua:4: attempt to index global 'lyaml' (a nil value)) 
Aborted 

所以我想,有没有lyaml符号和require()电话不知何故失败。

通过阅读luaL_requiref()文档我想modname将通过其呼叫glb标志设置为true设置:

void luaL_requiref (lua_State *L, const char *modname, 
        lua_CFunction openf, int glb); 

Calls function openf with string modname as an argument and sets the call result in package.loaded[modname] , as if that function has been called through require .

If glb is true, also stores the result into global modname .
Leaves a copy of that result on the stack.

我试图评论在Lua脚本require()电话,结果是一样的。

问题

我做错了什么?我忘了做点什么吗?


编辑

我砍死模块更新弃用(删除)功能/类型及其替代品如下:

lua_strlen() -> luaL_len() 
luaL_reg  -> luaL_Reg 
luaL_getn() -> luaL_len() 

但是使用lyaml工作Lua脚本,所以我觉得这个问题是不是我的黑客。

我试着用Lua 5.1原版lyaml模块。结果是一样的,所以我敢肯定这个问题不是我的破解。

UPDATE

添加下面的行,由道格·柯里在他的回答表明,C程序和Lua 5.1完美。但我仍然在5.2中遇到同样的错误。

lyaml = require('lyaml') 
+0

“我攻击了模块,使其与Lua 5.2配合使用。”你是否“正确”*“黑客”?如果你没有使用原始模块,那么没有看到你的实际代码就无法知道它能正常工作。此外,Luabind与此有什么关系? 'lyaml'使用那个吗? – 2012-07-14 17:49:21

+0

@NicolBolas抱歉[luabind]我没有提及使用它。我添加了关于黑客的进一步解释。 – dave 2012-07-14 17:59:43

+0

@NicolBolas正如我在更新中报道的那样,我使用Lua 5.1和最初的'lyaml'模块运行相同的场景。结果是一样的。我想说,在投票结束之前询问有关问题的进一步信息将是一种良好的做法和尊重的问题。谢谢。 – dave 2012-07-14 18:41:50

回答

5

foo.lua书面只会在Lua 5.1.x中运行 - 你砍死lyaml.c不设置全局lyaml而且也不需要在Lua 5.2。我怀疑你的PATH没有Lua 5.2,当你运行第一个测试“像魅力一样工作”,或者你在加载foo.lua之前手动设置lyaml

foo.lua应该先从

lyaml = require('lyaml') 
+0

'foo.lua'可以与Lua 5.1和5.2一起使用。我甚至可以在两个版本中都要求('lyaml')'并与模块交互工作。当我尝试从C程序中调用'hello()'时出现问题。我如何设置全球'lyaml'?我试着用'luaL_requiref()'写成,没有成功。谢谢。 – dave 2012-07-15 00:19:53

+0

只要'lyaml.so'的'luaopen_lyaml'返回模块表,看起来在git仓库中正确执行,请参阅我的5.1和5.2兼容方法的附录。 – 2012-07-15 04:06:56

+0

添加'lyaml = require('yaml')'使得C程序在5.1下工作!在5.2中返回相同的错误...不明白为什么。默认情况下,Lua使用'-DLUA_COMPAT_ALL'进行编译。 – dave 2012-07-15 08:38:30

5

我解决了......一切问题的根源是一个不好用的luaL_requiref()

阅读this thread我得到受此启发跟进:

In Lua 5.2, libraries no longer create globals; they just return the library table.

luaL_openlibs calls luaL_requiref instead of calling luaopen_* , and luaL_requiref sets the corresponding globals.

所以需要调用luaL_requiref()加载模块,并设置lyaml全球。

如在使用

luaL_requiref(L, "lyaml", luaopen_package, 1); 

我想这个问题说,但它是完全错误的,因为luaopen_package()是Lua的标准package模块加载功能...我不得不改用:

luaL_requiref(L, "lyaml", luaopen_lyaml, 1); 

并用

gcc -L/path/to/5.2 -Wall -o foo foo.c -ldl -lm -llua -l:lyaml.so.1 

得到引用ces到luaopen_lyaml()


在Lua的5.1,为道格·柯里说,这足以发出

lyaml = require('lyaml') 
hello.lua

,没有C程序调用luaL_requiref()