2
13
2014
1

Lua的函数调用和协程中,栈的变化情况

 
 
 
1. lua_call / lua_pcall
 
对于这两个函数,对栈底是没有影响的——调用的时候,参数会被从栈中移除,当函数返
回的时候,其返回值会从函数处开始压入,可以通过新的栈顶减去旧的栈顶得到返回值数
量。
 
2. lua_yield
 
对 Lua 函数来说, yield相当于只是在调用一个函数,对C函数也是这样。yield的参数
是返回值的数量,这些返回值会被返回给resume,见下。
 
2. lua_resume
 
resume是最复杂的一个函数:首先,第一次调用的时候,它相当于是个lua_call,也就是
说,被resume的那个函数只能看到自己的参数在栈顶,更低的就看不见了。其次,当函数
被yield之后,resume返回,这时resume的栈顶只有yield返回的参数,其他的栈元素是看
不到的。
在这个基础上,coroutine的状态是LUA_YIELD,如果需要继续执行,就需要再次 resume
,这里就有一些微妙的区别了。在这种情况下,resume的nargs参数是无用的——也就是
说,无论你传递的是多少,所有栈顶的元素都会被返回给yield,也就是说,如果需要在
返回之前清除掉栈,那么就需要你自己手动去清除,然后再resume。
 
下面是测试的示例代码:
 
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>

int luv_dumpstack(lua_State *L) {
    int i, top;
    printf("-------------------\n");
    printf("dumpstack: L=%p\n", L);
    top = lua_gettop(L);
    printf("top: %d\n", top);
    for (i = 1; i <= top; ++i) {
        printf("[%d][%s]: %s\n",
                i,
                luaL_typename(L, i),
                luaL_tolstring(L, i, NULL));
        lua_pop(L, 1);
    }
    printf("-------------------\n");
    return top;
}

static int cont(lua_State *L) {
    printf("stack after yield\n");
    luv_dumpstack(L);
    lua_pushinteger(L, 21);
    lua_pushinteger(L, 22);
    lua_pushinteger(L, 23);
    return lua_gettop(L);
}

static int test_yield(lua_State *L) {
    printf("stack before yield\n");
    luv_dumpstack(L);
    lua_pushinteger(L, 1);
    lua_pushinteger(L, 2);
    lua_pushinteger(L, 3);
    lua_pushinteger(L, 4);
    lua_pushinteger(L, 5);
    return lua_yieldk(L, 2, 0, cont);
}

static int test_resume(lua_State *L) {
    lua_State *L1 = lua_newthread(L);
    lua_pushinteger(L1, 11);
    lua_pushinteger(L1, 12);
    lua_pushcfunction(L1, test_yield);
    lua_pushinteger(L1, 13);
    lua_pushinteger(L1, 14);
    lua_pushinteger(L1, 15);
    printf("stack before resume\n");
    luv_dumpstack(L1);
    printf("resume: %d\n", lua_resume(L1, L, 3));
    printf("stack after resume\n");
    luv_dumpstack(L1);
    lua_pushinteger(L1, 24);
    lua_pushinteger(L1, 25);
    printf("stack before second resume\n");
    luv_dumpstack(L1);
    /* XXX notice even we pass 2, all values in stack (4,5,24,25)
     * will passed to coroutine */
    printf("resume: %d\n", lua_resume(L1, L, 2));
    printf("stack after second resume\n");
    luv_dumpstack(L1);
    return 0;
}


int main(void) {
    lua_State *L = luaL_newstate();
    lua_pushcfunction(L, test_resume);
    lua_call(L, 0, 0);
    lua_close(L);
    return 0;
}
/* cc: libs+='-llua52' */

 

Category: 未分类 | Tags: | Read Count: 13949
Avatar_small
文杰 说:
Apr 11, 2014 05:51:01 PM

大侠,我想从头开始学习lua,发现只有3本中文的书籍,programing in lua和 lua 游戏编程,lua手册。其他的也没找到很好的资料,应该怎么学习呢,想深入学习怎么办呢?
希望您能指点一下,谢谢!!


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com