Comments (11)
Hi, do you have an example script to reproduce the bug ? i would like to try fixing it to continue supporting the tostring() as it allows the user to use the __tostring metamethod for both userdata and tables
from luamachine.
-- correctly prints 'userdata' as this is a UFunction defined in the LuaState Table TMap
print(type(spawnprojectile))
local coro = coroutine.create(function()
coroutine.yield()
coroutine.yield('one', 'two', 'three', 'four', 'five')
coroutine.yield(17)
-- prints false, instead of hello
print("hello")
-- prints 'nil' with current print C function, prints "string" with replacement method above so looks like something is going wrong with the UFunction wrapping in a coroutine too
print(type(spawnprojectile))
return coroutine.yield('ended')
end)
-- call as global per tick from level BP
unreal_tick = function()
do
local alive = coroutine.resume(coro)
if alive then
return print("alive")
end
end
end
from luamachine.
Unless I am missing something, tostring just calls luaB_tostring https://github.com/lua/lua/blob/c6f7181e910b6b2ff1346b5486a31be87b1da5af/lbaselib.c#L500
which is
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
lua_tostring is a define for lua_tolstring #define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
TableFunction_print breaks the Lua coroutine -> C -> Lua -> C barrier limitation when using the "tostring" global and pcalling it. Lua uses setjmp/longjmp for coroutines, so the second Lua -> C call clobbers the stack frame.
Doesn't explain the weirdness with UFunction wrappiing and coroutines I'm seeing, for some reason accessing within a coroutine makes it think the userdata is a string, whether or not it has already been cached C++ side.
from luamachine.
Your intuition was right, the stack was clobbered by the pcall usage. I have used lua_call instead (in the same way as the original print) and your code worked. Thanks a lot.
Note: in this way the user can continue overriding the global tostring()
from luamachine.
Ok, great and you're right on the tostring override flexibility 👍
Unfortunately, the first print outside the coroutine is correctly outputting type "userdata" for a blueprint UFunction exposed by the LuaState Table property. Whereas the print inside the coroutine, prints type 'string'
I can look into this a bit more and try and see why... from the sample code above:
-- correctly prints 'userdata' as this is a UFunction defined in the LuaState Table TMap
print(type(spawnprojectile))
-- prints "string" when called from the coroutine
print(type(spawnprojectile))
from luamachine.
I think i have found the issue: when a coroutine spawns it inherits the ULuaState instance from the parent, but the lua_State contained in it is different from the one of the thread/coroutine, basically destroying the stack. I am trying to find a solution
from luamachine.
Aha! I was just adding the stuff below the separator...
Wondering about the convert to LuaValue then immediately back to string, why not use Messages.Add(FString(UTF8_TO_TCHAR(s)))?
const char *s = lua_tostring(L, -1);
if (!s)
return luaL_error(L, "'tostring must return a string to 'print'");
FLuaValue Value(FString(UTF8_TO_TCHAR(s)));
LuaState->Pop();
Messages.Add(Value.ToString());
One other note, it might be good if pcall wasn't hiding behind LuaState::Call as there is an explicit LuaState::PCall and could cause some subtle hard to track down issues?
bool ULuaState::Call(int NArgs, FLuaValue& Value, int NRet)
{
if (lua_pcall(L, NArgs, NRet, 0))
{
I think there is still a problem with the stack:
-- correctly prints "hello"
print("hello")
-- does not print anything
print("hello", "goodbye")
coro = coroutine.create(function()
-- suspend function (without returning values)
coroutine.yield()
-- suspend returning 5 values
coroutine.yield('one', 'two', 'three', 'four', 'five')
-- correctly prints "hello"
-- print("hello")
-- does not print anything
print("hello", "goodbye")
-- suspend returning 1 value
coroutine.yield(17)
-- suspend returning 1 value
coroutine.yield('ended')
end)
-- run the coroutine until the first yield
alive = coroutine.resume(coro)
-- ... until second yield (it returns five values)
alive, one, two, three, four, five = coroutine.resume(coro)
-- ... until third yield
alive, seventeen = coroutine.resume(coro)
-- ... the last yield
alive, ended = coroutine.resume(coro)
-- complete the coroutine
alive = coroutine.resume(coro)
-- this time 'alive' will be 'false' as the coroutine is 'dead' (it has finished its work)
alive = coroutine.resume(coro)
from luamachine.
Just a quick note that with f95db66 the following moonscript using Lumen is working :)
Pretty involved diff, could be a few corner cases maybe with thread LuaValues
dbg = require "debugger"
sched = require "lumen.sched"
-- task emits 5 signals and pauses itself.
emitter_task = sched.new_task(->
while true
for i=1, 5
sched.signal('ev', i)
sched.sleep(1)
sched.running_task\set_pause(true)
)
-- if stop receiving signals, un-pause the emitter task.
sched.run(->
waitd={timeout:5, 'ev'}
while true
ev, s = sched.wait(waitd)
if ev
spawnprojectile!
print(s)
else
print ('wakeup!')
emitter_task\set_pause(false)
)
emitter_task\run()
export unreal_tick = ->
sched.step!
from luamachine.
I have refactored the whole "sub-states" (thread/coroutines) management.
Can you try the latest code ?
Thanks
from luamachine.
I tested with f95db66, check the last comment above :) I also tested debugging and the stacks/locals/upvalues inside the coroutines are correct. Nice work!
from luamachine.
Note: i have added a new blueprint utility function LuaValueResumeMulti that can be used instead of manually calling coroutine.resume().
from luamachine.
Related Issues (20)
- Return with "Lua Create Object" returns received parameter instead HOT 4
- Supporting different platforms HOT 1
- Data Validation Error
- Lua Run File Doesnt Work HOT 10
- Multiple states from different files? HOT 5
- Issues with packaging HOT 7
- Make LUA value keeps losing the type HOT 2
- Is there a way to run automation tests in lua?
- Server and Client sharing LuaState in single process PIE HOT 4
- UE5: Couldn't build on linux as PlatformFilemanager.h was renamed HOT 2
- How to package with `LuaCode`? HOT 1
- Access Error Outside of State File HOT 1
- Q: is possible to create an animation sequence with LuaMachine like c++? HOT 3
- Missing includes when packaging plugin but does not affect source build HOT 5
- Assigning a metatable to _G HOT 2
- How calling functions in sequence with Delay.
- Support UTF-8 files with BOM encoding attached.
- UE 5.3 support not on the marketplace
- 4.27 version doesnt work with 4.27.2 HOT 3
- Projects using LuaMachine
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 luamachine.