Comments (5)
GopherLua is a Lua5.1 implementation.
So codes that does not work in the original C-Lua 5.1 implementation does not work in the GopherLua too.
It seems that your code does not work in the original C-Lua.
#include <stdio.h>
#include "lua.h"
int main(int argc, char **argv) {
lua_State *L;
lua_State *co;
int i;
int status;
L = (lua_State*)luaL_newstate();
luaopen_base(L);
co = lua_newthread(L);
if (luaL_loadfile(co, "test.lua")) {
printf("%s\n", lua_tostring(co, lua_gettop(co)));
lua_close(co);
return;
}
for(i = 0; i < 20; i++) {
lua_pushstring(co, "tick");
lua_pushinteger(co, i);
status = lua_resume(co, 2);
if(status == LUA_ERRRUN && lua_isstring(co, -1)) {
printf("Error: %s", lua_tostring(co, -1));
lua_pop(co, 1);
break;
}
}
lua_close(L);
return 0;
}
This code generates an error: "Got Error: attempt to yield across metamethod/C-call boundary".
from gopher-lua.
That is a seperate issue in C-Lua that can be worked around with the following Lua code, however it's because the coroutine yield is trying to pass through the pcall stack, which can't be serialised in the C Lua stack as a sane value without a patch to the VM. I would note that this work-around doesn't work with Gopher-Lua.
xpcall = function( _fn, _fnErrorHandler )
local typeT = type( _fn )
assert( typeT == "function", "bad argument #1 to xpcall (function expected, got "..typeT..")" )
local co = coroutine.create( _fn )
local tResults = { coroutine.resume( co ) }
while coroutine.status( co ) ~= "dead" do
tResults = { coroutine.resume( co, coroutine.yield() ) }
end
if tResults[1] == true then
return true, unpack( tResults, 2 )
else
return false, _fnErrorHandler( tResults[2] )
end
end
pcall = function( _fn, ... )
local typeT = type( _fn )
assert( typeT == "function", "bad argument #1 to pcall (function expected, got "..typeT..")" )
local tArgs = { ... }
return xpcall(
function()
return _fn( unpack( tArgs ) )
end,
function( _error )
return _error
end
)
end
from gopher-lua.
Hmmm, your work-around works for me( it seems the same result with C-Lua5.1.4).
test.go
package main
import (
"fmt"
"github.com/yuin/gopher-lua"
)
func main() {
state := lua.NewState()
main, err := state.LoadFile("test.lua")
if err != nil {
panic(err)
}
thread := state.NewThread()
s := lua.ResumeOK
for i := 0; i < 20; i++ {
if s != lua.ResumeError {
s, err, _ = state.Resume(thread, main, lua.LString("tick"), lua.LNumber(i))
if err != nil {
fmt.Println("Error: ", err)
break
}
}
}
}
test.lua
require("workaround")
local ok, err = pcall(
function()
local evt, n = coroutine.yield()
print("Tick: " .. n)
if n > 10 then
error("N is > 10")
end
end)
if not ok then
print("Got Error: " .. tostring(err))
error("Dying.")
end
workaround.lua
xpcall = function( _fn, _fnErrorHandler )
local typeT = type( _fn )
assert( typeT == "function", "bad argument #1 to xpcall (function expected, got "..typeT..")" )
local co = coroutine.create( _fn )
local tResults = { coroutine.resume( co ) }
while coroutine.status( co ) ~= "dead" do
tResults = { coroutine.resume( co, coroutine.yield() ) }
end
if tResults[1] == true then
return true, unpack( tResults, 2 )
else
return false, _fnErrorHandler( tResults[2] )
end
end
pcall = function( _fn, ... )
local typeT = type( _fn )
assert( typeT == "function", "bad argument #1 to pcall (function expected, got "..typeT..")" )
local tArgs = { ... }
return xpcall(
function()
return _fn( unpack( tArgs ) )
end,
function( _error )
return _error
end
)
end
test.c
#include <stdio.h>
#include "lua.h"
int main(int argc, char **argv) {
lua_State *L;
lua_State *co;
int i;
int status;
L = (lua_State*)luaL_newstate();
luaL_openlibs(L);
co = lua_newthread(L);
if (luaL_loadfile(co, "test.lua")) {
printf("%s\n", lua_tostring(co, lua_gettop(co)));
lua_close(co);
return;
}
for(i = 0; i < 20; i++) {
lua_pushstring(co, "tick");
lua_pushinteger(co, i);
status = lua_resume(co, 2);
if(status == LUA_ERRRUN && lua_isstring(co, -1)) {
printf("Error: %s", lua_tostring(co, -1));
lua_pop(co, 1);
break;
}
}
lua_close(L);
return 0;
}
GopherLua(master) prints
Tick: 1
Error: can not resume a dead thread
C-Lua(5.1.4) prints
Tick: 1
Error: attempt to call a nil value
from gopher-lua.
Hrm, it would seem I'm misunderstanding something in the stack then. I'll do some more digging tomorrow and comment if I can find anything.
from gopher-lua.
Due to lack of your response I am closing this issue for now.
Please feel free to reopen this issue if you have any questions.
from gopher-lua.
Related Issues (20)
- [ HELP!] How to revert Lua AST to lua source code?
- Preload other lua files
- L.DoFile does not work when i require a so in lua script
- Wrong result of multi-assignment HOT 2
- Function names do not support UTF-8/Unicode
- Virtual machine interfaces need to be advertised
- bug: pcall affecting function upvalues HOT 4
- xpcall with error in error handler returns (nil, nil)
- The parameter passed by xpcall is nil
- different behavior in read function HOT 1
- Expand fopen modes
- different behavior in io.popen function
- Incorrect behavior for string.gmatch
- stuck when xpcall HOT 3
- LNumber.String() use strconv instead of fmt.Sprint HOT 1
- Can't require lua-cjson
- tonumber doesn't handle E notation correctly HOT 1
- 【BUG】panic: runtime error: index out of range [1048577] with length 1048577 HOT 2
- os.execute not behaving correctly on windows
- Result of L.DoString with coercion is not correct
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gopher-lua.