Lua 5.2 C API and require
Solution 1
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. 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
.
foo.lua
should start with
lyaml = require('lyaml')
Solution 2
I solved... the root of all problems was a bad use of luaL_requiref()
.
Reading this thread i got inspired by this follow up:
In Lua 5.2, libraries no longer create globals; they just return the library table.
luaL_openlibs
callsluaL_requiref
instead of callingluaopen_*
, andluaL_requiref
sets the corresponding globals.
so it is necessary to call luaL_requiref()
to load the module and set the lyaml
global.
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:
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()
.
In Lua 5.1, as Doug Currie said, it was enough to issue
lyaml = require('lyaml')
in hello.lua
, without calling luaL_requiref()
in C program.
Comments
-
dave almost 2 years
Issue
I want to call a Lua script which
require()
slyaml
module, Lua binding for LibYAML, from a C program.I compiled Lua 5.2 from source and I hacked the module to make it work with Lua 5.2. It can be found on github.
The Lua script follows, it works either with Lua 5.1 and 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.The C program follows:
/* 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: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 afterluaL_openlibs()
call: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 therequire()
call fails somehow.By reading
luaL_requiref()
documentation I thoughtmodname
would be set by its call settingglb
flag to 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
.
If glb is true, also stores the result into globalmodname
.
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.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.I tried original
lyaml
module with Lua 5.1. Results are the same, so I'm sure the problem is not my hack.UPDATE
Adding the following line, as suggested by Doug Currie in his answer, the C program works perfectly with Lua 5.1. I still get the same error in 5.2 though.
lyaml = require('lyaml')