Why am I getting a thread instead of my parameters

2019-07-27 12:22发布

问题:

I am using lua 5.3 from my C/C++ game to allow certain parts of its behavior to be scripted.

From the C++ program, every frame I call the lua function main in the following manner:

lua_getfield(VMState, LUA_GLOBALSINDEX, "main");
int result = lua_pcall(VMState, 0, 0, 0);

I expect the script to define a function called main, which does a bunch of stuff. For example, I can have a script that does something like this:

local f = function()
    draw_something({visible = true, x = 0, y = 0})
end

main = function()
    f()
end

draw_something() is a callback to the C code, which does something interesting with the parameters passed:

lua_getfield(VMState, 1, "visible");
bool visible = (bool)lua_toboolean(VMState, 2); lua_pop(VMState, 1);
if (!visible)
    return;
// Do some other stuff

Of interest, is that by the time this callback is called, the anonymous table I passed as a parameter to do_something in the lua side, is now at stack position 1, so I can call lua_getfield() from the C side, to access the "visible" field, and do something with it.

This works pretty well, and I've done lots of stuff like this for years.

Now, I want to convert the lua call to f to a coroutine, so I do something like this from the lua side:

local f = function()
    draw_something({visible = true, x = 0, y = 0})
end

local g = coroutine.create(function()
    while true do
        f()
        coroutine.yield()
    end
end

main = function()
    coroutine.resume(g)
end

The result should be the same. However, it now turns out that by moving the call to draw_something() inside a coroutine, the parameter I had passed to the function, which should have been a table, is now a thread? (lua_istable() returns 0, while lua_isthread() returns 1).

Interestingly, it doesn't matter how many parameters I pass to my function: 0, 1, 4, 50, from inside the callback I'm only getting one parameter, and it is a thread.

For some reason, this is happening with some functions that I exported, but not all. I can't see any difference in the way I'm exporting the different functions though.

Is there any reason why lua would switch my parameters to a thread?

回答1:

I found the answer.

It turns out that the lua_State that is passed to you on a lua_CFunction is not guaranteed to be the same to the one you first got on lua_newstate()

I suppose that each coroutine might get its own separate lua_State. If you always do stuff on the lua_State you got on lua_newstate(), you might have problems with coroutines, so you have to ensure you always use the lua_State you got passed on your lua_CFunction.



标签: lua coroutine