Lua 跨C调用边界产生yield

我正在尝试在调试钩子中调用lua_yield,并在输出中得到此错误。我想要在处理了一定数量的指令后产生yield,并希望这是实现的方法。

我使用一些Python ctypes绑定编写了这个程序。

yielding
b'test.lua:1: attempt to yield across C-call boundary'

我认为这应该可以工作,因为我正在使用LuaJIT,它具有完全可恢复的VM

@lua_Hook
def l_dbg_count(L: lua_State_p, ar: ctypes.POINTER(lua_Debug)):
    if ar.contents.event == EventCode.HookCount:
        print("yielding")
        lua_yield(L, 0)

#main method
def main():
    ...
    lua_sethook(L, l_dbg_count, DebugEventMask.Count, 1)
    luaL_loadfile(L, b"test.lua")
    ret = lua_pcall(L, 0, 0, 0)
    while True:
        if ret != LuaError.Ok and ret != LuaError.Yield:
            print(lua_tostring(L, -1))
            break
        elif ret == LuaError.Yield:
            print("resuming")
            ret = lua_resume(L, None, 0)
    lua_close(L)
点赞
用户249552
用户249552

我必须首先使用 lua_newthread 推送一个新的线程,然后调用 luaL_loadfile,并且不使用 lua_pcall,而是使用 lua_resume

我将它重写成了 C 语言,以检查在从 Lua 到 Python 的堆栈展开过程中是否存在可能的问题。

void l_dbg_count(lua_State *L, lua_Debug *ar) {
    if(ar->event == LUA_HOOKCOUNT) {
        printf("yielding\n");
        lua_yield(L, 0);
    }
}

...

int main(int argc, char **argv) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_sethook(L, l_dbg_count, LUA_MASKCOUNT, 5);

    lua_State *L_t = lua_newthread(L);
    luaL_loadfile(L_t, "test.lua");
    int ret = lua_resume(L_t, 0);
    while(true) {
        if(ret != 0 && ret != LUA_YIELD) {
            fprintf(stderr, "%s", lua_tostring(L_t, -1));
            break;
        } else if(ret == LUA_YIELD) {
            printf("resuming\n");
            ret = lua_resume(L_t, 0);
        } else {
            break;
        }
    }

    lua_close(L);
    return EXIT_SUCCESS;
}

然而,这似乎破坏了协同程序库的工作,因此目前正在寻找可能的解决办法。

2021-01-11 11:55:44