1.內部使用C的longjmp機制放棄壹個契約。?所以,如果壹個c函數foo調用壹個API函數,而這個API函數yield(直接或間接調用yield函數)。Lua不能返回foo,因為longjmp會移除C棧的棧幀。
2.為了避免這類問題,在API調用中調用yield時,除了那些拋出錯誤的API,還提供了三個函數:lua_yieldk、Lua _ call、lua_pcallk。當yield發生時,它們可以從傳入的continuation函數(參數名為k)繼續運行。
3.我們需要預設壹些術語來解釋延續點。?對於從Lua調用的c函數,我們稱之為原函數。?上面提到的從這個原始函數調用的三個C API函數稱為被調用函數。被調用的函數可以讓當前線程屈服。(yield發生在被調用的函數是lua_yieldk,或者lua_callk或lua_pcallk傳入的函數調用yield時。)
4.假設正在運行的線程在執行被調用的函數時讓步。?當這個線程再次被擴展時,它希望繼續被調用函數的操作。但是,被調用的函數是不可能返回到原函數的。這是因為之前的yield操作破壞了C棧的棧幀。相反,Lua調用作為被調用函數的參數給出的continuation函數。顧名思義,延續函數將延續原函數的任務。
5.註意這裏對continuation函數的額外顯式調用:Lua只會在需要的時候調用continuation函數,這可能是因為出錯也可能是因為yield需要繼續運行。如果沒有yield,被調用的函數正常返回,那麽lua_pcallk(和lua_callk)也會正常返回。(當然,在這個例子中,妳可以不在後面調用continuation函數,而是直接把需要做的工作寫在原函數被調用之後。)
6.Lua會把延續函數當成原函數。?延續函數會收到和原函數壹樣的lua棧,收到的Lua狀態也和被調用函數如果返回應該有的狀態壹致。(比如lua_callk被調用後,之前在堆棧中推送的函數和調用參數都被調用生成的返回值所替代。)這時也具有同樣的價值。當它返回時,Lua會把它當作原函數的返回來操作。
7.我們需要預設壹些術語來解釋延續點。?對於從Lua調用的c函數,我們稱之為原函數。上面提到的從這個原始函數調用的三個C API函數稱為被調用函數。被調用的函數可以讓當前線程屈服。(yield發生在被調用的函數是lua_yieldk,或者lua_callk或lua_pcallk傳入的函數調用yield時。)
8.假設正在運行的線程在執行被調用的函數時讓步。?當這個線程再次被擴展時,它希望繼續被調用函數的操作。但是,被調用的函數是不可能返回到原函數的。這是因為之前的yield操作破壞了C棧的棧幀。相反,Lua調用作為被調用函數的參數給出的continuation函數。顧名思義,延續函數將延續原函數的任務。
希望能幫到妳,謝謝!