简体   繁体   English

Lua 5.2 C API和要求

[英]Lua 5.2 C API and require

Issue 问题

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


Problem 问题

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 string modname as an argument and sets the call result in package.loaded[modname] , as if that function has been called through require . 调用函数openf并将字符串modname作为参数,并在package.loaded[modname]设置调用结果,就好像该函数已通过require调用一样。

If glb is true, also stores the result into global modname . 如果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()调用,结果是一样的。

Question

What did I do wrong? 我做错了什么? Am I forgetting to do something? 我忘了做某事吗?


EDIT 编辑

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. 结果是一样的,所以我确定问题不是我的黑客。

UPDATE UPDATE

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 calls luaL_requiref instead of calling luaopen_* , and luaL_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.

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