본문 바로가기

프로그램언어/Lua

LuaApi

 
serious-code.net  LuaApi/State UserPreferences
 
HelpContents Search Diffs Info Edit Subscribe XML Print View Up
lua_open, lua_close,

1 lua_open

    lua_State *lua_open (void); 
    루아 가상 머신을 생성한다.


2 lua_close

    void lua_close (lua_State *L); 
    루아 가상 머신을 종료한다.




lua_push..., lua_pushcclosure, lua_pushfstring, lua_concat, lua_type, lua_is..., lua_to..., lua_gettop, lua_settop, lua_pushvalue, lua_remove, lua_insert, lua_replace, lua_checkstack,


1 lua_push...

    void lua_pushboolean       (lua_State *L, int b); 
    void lua_pushnumber (lua_State *L, lua_Number n);
    void lua_pushlstring (lua_State *L, const char *s, size_t len);
    void lua_pushstring (lua_State *L, const char *s);
    void lua_pushnil (lua_State *L);
    void lua_pushcfunction (lua_State *L, lua_CFunction f);
    void lua_pushlightuserdata (lua_State *L, void *p);
    push 시리즈 함수들은 딱히 특별할 것이 없다. 그냥 스택에다 해당하는 타입의 아이템을 푸쉬한다. 루아에서는 문자열이 0으로 끝나야만 하는 것이 아니기 때문에 -- 어떤 바이너리 값도 될 수 있다 -- lua_pushlstring 함수가 존재한다. 일반적인 C 문자열인 경우에는 그냥 lua_pushstring 함수를 사용하면 된다.


2 lua_pushcclosure

    void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); 
    C 함수에다 upvalue를 할당해서 closure를 만들기 위해 사용하는 함수다. upvalue나 closure에 관한 것은 LuaGlossary 페이지를 참고하기 바란다. fn은 C 함수에 대한 포인터이고, n은 upvalue의 갯수다. 이 함수를 호출하기 전에 upvalue로 사용할 아이템들을 스택에다 n개만큼 푸쉬해둬야 한다. lua_pushcclosure 호출 후에는 푸쉬했던 아이템들이 모두 팝되고, 생성된 closure가 스택의 맨 위에 푸쉬된다.
    호출 전의 스택                       호출 후의 스택  
    +---------+ +---------+
    | upvalue | | closure |
    +---------+ +---------+
    | upvalue | | ... |
    +---------+ +---------+
    | ... | | ... |
    +---------+ +---------+
    임의의 C 함수를 1개의 int형 upvalue와 함께 등록하기 위해서는 다음과 같이 하면 된다.
    static int counter(lua_State* L); // 어딘가에 선언되어 있는 C 함수 

    ...

    int create_closure(lua_State* L)
    {
    lua_pushnumber(L, (double)997); // upvalue로 사용할 값을 스택에다 푸쉬
    lua_pushcclosure(L, &counter, 3); // closure 생성
    return 1; // 스택의 맨 위에 closure가 1개 푸쉬되었으므로...
    }
    위의 예제에서 counter 함수가 upvalue를 사용하는 함수라는 것을 알 수 있다. upvalue를 액세스하기 위해서는 lua_upvalueindex 함수를 사용한다.
    static int counter(lua_State* L) 
    {
    int val = (int)lua_tonumber(L, lua_upvalueindex(1)); // upvalue를 읽어온다.
    lua_pushnumber(L, ++val); // 증가시킨 값을 푸쉬한다.
    lua_pushvalue(L, -1); // 방금 푸쉬한 값을 복사해서 다시 푸쉬한다.
    lua_replace(L, lua_upvalueindex(1)); // 복사해서 푸쉬한 값으로 upvalue를 치환한다.
    return 1;
    }


3 lua_pushfstring

    const char* lua_pushfstring(lua_State *L, const char *fmt, ...); 
    sprintf 함수와 같이 포맷과 인수들을 받아들여, 문자열을 생성한 다음, 그 문자열을 스택에다 푸쉬하고, 그 문자열의 포인터를 반환한다. sprintf 처럼 다양한 포맷을 지원하지는 않으며, 현재 지원하는 포맷은 %%('%' 문자를 위해), %s(문자열), %d(정수), %f(더블), %c(캐릭터) 정도이다.


4 lua_concat

    void lua_concat (lua_State *L, int n); 
    스택에서 n개만큼의 아이템을 팝해서, 그것을 모두 문자열로 변환해 합친 다음, 푸쉬한다. 숫자 같은 경우에는 자동으로 문자열로 변환하고, 다른 타입 같은 경우, 문자열로 변환하기 위해 메타 메서드를 호출하기도 한다.
    lua_concat(L, 2); 

    호출 전의 스택 호출 후의 스택
    +----------+
    | "world" |
    +----------+ +---------------+
    | "hello " | | "hello world" |
    +----------+ +---------------+
    | ... | | ... |
    +----------+ +---------------+


5 lua_type

    int lua_type(lua_State *L, int index); 
    지정된 위치의 스택에 있는 아이템의 종류를 반환한다. 반환하는 종류는 lua.h에 나와있다. LUA_TNIL, LUA_TBOOLEAN, LUA_TNUMBER, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD 정도다.


6 lua_is...

    int lua_isnil           (lua_State *L, int index); 
    int lua_isboolean (lua_State *L, int index);
    int lua_isnumber (lua_State *L, int index);
    int lua_isstring (lua_State *L, int index);
    int lua_istable (lua_State *L, int index);
    int lua_isfunction (lua_State *L, int index);
    int lua_iscfunction (lua_State *L, int index);
    int lua_isuserdata (lua_State *L, int index);
    int lua_islightuserdata (lua_State *L, int index);
    지정된 위치의 스택에 있는 아이템이 해당하는 타입으로 변환될 수 있는 값인가를 반환하는 함수들이다. 즉 숫자들의 경우, lua_isnumber 함수를 만족할 뿐만 아니라, lua_isstring 함수 역시 만족한다. 실제 타입을 알아내기 위해서는 lua_type 함수를 사용해야 한다.


7 lua_to...

    int            lua_toboolean   (lua_State *L, int index); 
    lua_Number lua_tonumber (lua_State *L, int index);
    const char *lua_tostring (lua_State *L, int index);
    size_t lua_strlen (lua_State *L, int index);
    lua_CFunction lua_tocfunction (lua_State *L, int index);
    void *lua_touserdata (lua_State *L, int index);
    lua_State *lua_tothread (lua_State *L, int index);
    void *lua_topointer (lua_State *L, int index);
    지정된 위치의 스택에 있는 아이템을 해당하는 타입으로 변환해서 반환한다. 지정된 인덱스의 아이템이 해당 타입으로 변환이 불가능한 타입이거나, 인덱스 자체가 잘못된 경우 모두 0 또는 NULL을 반환한다.

    lua_tostring 함수의 경우, 반환한 문자열 아이템이 스택에서 팝되는 경우, 가비지 컬렉션에 의해 언제 사라질 지 알 수 없다. 그러므로 문자열을 계속 보관하기를 원한다면 복사를 해두어야 한다. 루아에서 문자열은 반드시 0으로 끝나는 것이 아니기 때문에, 복사를 할 때, 먼저 lua_strlen 함수를 이용해 길이를 조사해야 한다.


8 lua_gettop

    int lua_gettop (lua_State *L); 
    스택에 들어있는 아이템들의 갯수를 반환한다. 즉 이 함수가 반환하는 값은 가장 최근에 푸쉬된 아이템의 스택 인덱스와 같다.


9 lua_settop

    void lua_settop (lua_State *L, int index); 
    스택의 탑을 설정한다. 만일 10개의 아이템들이 스택에 들어있는데, index 값을 7로 줘서 이 함수를 호출하면, 7개의 아이템들만이 남고, 나머지 3개는 스택의 맨 위에서부터 버려진다. 반대의 경우, 즉 7개가 있는데 10을 index로 준 경우, nil 값이 모자란 갯수만큼 푸쉬된다. 사실 lua_pop 매크로가 이 함수를 이용한다.
    #define lua_pop(L,n) lua_settop(L, -(n)-1); 


10 lua_pushvalue

    void lua_pushvalue (lua_State *L, int index); 
    해당하는 위치에 있는 아이템을 복사해서 스택의 맨 위에다 푸쉬한다.
    lua_pushvalue(L, -1); 

    호출 전의 스택 호출 후의 스택
    +---------+
    | 999 |
    +---------+ +---------+
    | 999 | | 999 |
    +---------+ +---------+
    | 888 | | 888 |
    +---------+ +---------+
    | ... | | ... |
    +---------+ +---------+


11 lua_remove

    void lua_remove (lua_State *L, int index); 
    해당하는 위치에 있는 아이템을 스택에서 제거한다. index 위치보다 위에 있던 아이템들은 하나씩 내려온다.
    lua_remove(L, -2); 

    호출 전의 스택 호출 후의 스택
    +---------+
    | 999 |
    +---------+ +---------+
    | 888 | | 999 |
    +---------+ +---------+
    | 777 | | 777 |
    +---------+ +---------+
    | ... | | ... |
    +---------+ +---------+

12 lua_insert

    void lua_insert (lua_State *L, int index); 
    스택의 맨 위에 있는 아이템을 지정된 위치로 옮긴다. index 위치보다 위에 있던 아이템들은 하나씩 올라간다.
    lua_insert(L, -2); 

    호출 전의 스택 호출 후의 스택
    +---------+ +---------+
    | 999 | | 888 |
    +---------+ +---------+
    | 888 | | 999 |
    +---------+ +---------+
    | 777 | | 777 |
    +---------+ +---------+


13 lua_replace

    void lua_replace (lua_State *L, int index); 
    스택의 맨 위에 있는 아이템을 팝해서 지정된 위치에 있는 값으로 설정한다. 아이템의 이동은 없다.
    lua_replace(L, -3); 

    호출 전의 스택 호출 후의 스택
    +---------+
    | 999 |
    +---------+ +---------+
    | 888 | | 888 |
    +---------+ +---------+
    | 777 | | 999 |
    +---------+ +---------+


14 lua_checkstack

    int lua_checkstack (lua_State *L, int extra); 
    루아의 스택 크기를 늘릴 때 사용하는 함수다. 루아에서 C 함수를 호출하는 경우, 루아는 스택에 적어도 20개의 자리를 확보해준다. 즉 C 쪽에서 20개까지 아이템을 푸쉬할 수 있다는 말이다. 일반적인 경우 이걸로 충분하다. 그러나 이 크기를 늘려야 할 때도 있을 것이다.

    이 함수를 호출하면, 현재 스택에다가 extra 갯수만큼의 빈 자리를 추가한다. 참고로 extra 인수의 값을 음수로 줘서 스택의 크기를 줄이는 것은 불가능하다. 무시된다.

    성 공적으로 스택의 크기를 늘린 경우에는 1을 반환하고, 스택의 크기를 더 이상 늘릴 수 없는 경우에는 0을 반환한다. 참고로 스택의 최대 크기는 LUA_MAXCSTACK 값으로서 llimits.h 파일에 정의되어 있다. 기본값은 2048이다.





GarbageCollection

루아는 incremental mark-and-sweep 알고리즘을 이용한 가비지 컬렉션을 수행한다. 이 과정에 사용되는 변수에는 2가지가 있다. 하나는 garbage-collector pause 값, 나머지 하나는 garbage-collector step multiplier 값이다.

Garbage-collector pause 값은 새로운 사이클을 시작하기 위해 메모리가 얼마나 커질 때까지 기다리는 가에 대한 값이다. 이 값이 2라면 사용하는 메모리가 현재의 2배가 되면 가비지 컬렉션을 시작하겠다는 말이다. 이 값이 1보다 작으면 당장 가비지 컬렉션 사이클을 시작한다.

Garbage-collector step multiplier 값은 메모리 할당 속도와 가비지 컬렉션 속도와의 비율을 정한다. 잘 이해가 안 가는데, 어쨌든 이를 통해 가비지 컬렉션의 속도를 결정한다고 한다. 이 값이 1이라면 메모리 할당 속도와 가비지 컬렉션 속도가 일치한다는 말이며, 이 경우 가비지 컬렉션이 정상적으로 동작하지 않을 수도 있다. 기본값은 2인데, 이는 가비지 컬렉션이 메모리 할당에 비해 2배의 속도로 동작한다는 말이다.


옛날 버전은 lua_getgccount, getgcthreshold, setgcthreshold 등의 함수를 사용했었는데, 언제부터인지 lua_gc 함수 하나로 통일되었다. 자세한 것은 [WWW]공식 매뉴얼을 참고...

int lua_gc (lua_State *L, int what, int data); 




1 lua_newuserdata

    void *lua_newuserdata (lua_State *L, size_t size); 
    해당하는 크기의 메모리를 가진 full userdata를 생성해서 스택의 맨 위에다 푸쉬한 다음, 그 메모리 블록의 주소를 반환한다.


2 lua_pushlightuserdata

    void lua_pushlightuserdata (lua_State *L, void *p); 
    스택에다 light userdata, 즉 포인터를 푸쉬한다.


3 lua_isuserdata and lua_islightuserdata

    int lua_isuserdata      (lua_State *L, int index); 
    int lua_islightuserdata (lua_State *L, int index);
    해당하는 인덱스의 아이템이 full 또는 light userdata인지의 여부를 반환한다.


4 lua_touserdata

    void *lua_touserdata  (lua_State *L, int index); 
    해당하는 인덱스의 아이템이 full userdata인 경우 메모리 블럭의 주소를 반환하고, light userdata인 경우, 포인터 값을 반환한다. 인덱스가 잘못되었거나, 해당 인덱스의 아이템이 userdata가 아닌 경우에는 NULL을 반환한다.


lua_newtable, lua_gettable, lua_rawget, lua_settable, lua_rawset, lua_next, lua_rawgeti, lua_rawseti,


1 lua_newtable

    void lua_newtable (lua_State *L); 
    빈 테이블을 생성해서 스택의 제일 위에다 놓는다.

2 lua_gettable

    void lua_gettable (lua_State *L, int index); 
    테이블에 들어있는 값 중에 하나를 읽어와서 스택 맨 위에다 놓는다. index 값은 테이블의 위치다. 테이블에 있는 값 중, 어느 것을 뽑을 것인가를 정하기 위해서 스택의 제일 위에 있는 값을 키로 사용하고, 팝한다. 그러므로 lua_gettable 함수를 호출하기 전에 lua_push... 시리즈 중에 하나를 호출해서 키 값을 푸시해둬야 한다.
    lua_pushnumber(L, 1); // 테이블의 '1' 키에 대응하는 값을 원한다. 
    lua_gettable(L, t); // t는 테이블의 인덱스
    호출 전의 스택                   호출 후의 스택 
    +-------+ +-------+
    | key | | value |
    +-------+ +-------+
    | ... | | ... |
    +-------+ +-------+
    | ... | | ... |
    +-------+ +-------+
    이 함수는 테이블 안의 "index" 메타 메서드를 호출할 수도 있다. 이 경우 동작이 전혀 달라질 수 있다. 테이블 안의 값만을 원한다면, lua_rawget 함수를 사용해야 한다.

3 lua_rawget

    void lua_rawget (lua_State *L, int index); 
    lua_gettable 함수와 마찬가지로, 주어진 index 위치에 있는 테이블의 값 중에, 스택의 맨 위에 있는 값을 키로 사용해 뽑은 다음, 그 값을 스택의 맨 위에다 놓는다.

4 lua_settable

    void lua_settable (lua_State *L, int index); 
    스택에서 키와 값, 즉 2개의 값을 팝해서, 주어진 index 위치에 있는 테이블의 값으로 설정한다. 즉 lua_settable 함수를 호출하기 전에 두 개의 값을 푸쉬해둬야 한다.
    lua_pushnumber(L, key);    // 키를 푸쉬 
    lua_pushnumber(L, value); // 값을 푸쉬
    lua_settable(L, t); // 테이블의 값을 설정
    호출 전의 스택                   호출 후의 스택 
    +-------+ +-------+
    | value | | ... |
    +-------+ +-------+
    | key | | ... |
    +-------+ +-------+
    | ... | | ... |
    +-------+ +-------+
    이 함수는 테이블 안의 "settable"과 "newindex" 메타 메서드를 호출할 수도 있다. 순수하게 값을 설정하기만을 원한다면, lua_rawset 함수를 사용해야 한다.

5 lua_rawset

    void lua_rawset (lua_State *L, int index); 
    lua_settable 함수와 마찬가지로 스택에서 키와 값, 즉 2개의 값을 팝해서, 주어진 index 위치에 있는 테이블의 값으로 설정한다.

6 lua_next

    int lua_next (lua_State *L, int index); 
    테이블을 횡단(traverse)하기 위해서 사용하는 함수다. 호출할 때마다 스택의 맨 위에서 키를 팝한 다음, index 위치에 있는 테이블의 키와 해당하는 값을 스택에다 푸시한다. 최초에 횡단을 시작하기 위해서는 nil 값을 푸시해두면 된다. 더 이상 횡단할 쌍이 존재하지 않으면, lua_next 함수는 0을 반환한다.
    호출 전의 스택                   호출 후의 스택 
    +-------+ +-------+
    | key | | value |
    +-------+ +-------+
    | ... | | key |
    +-------+ +-------+
    | ... | | ... |
    +-------+ +-------+
    다음과 같은 형식으로 테이블을 횡단할 수 있다.
    // table is in the stack at index `t' 
    lua_pushnil(L); // first key
    while (lua_next(L, t) != 0)
    {
    // `key' is at index -2 and `value' at index -1
    printf("%s - %s\n",
    lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1)));
    lua_pop(L, 1); // removes `value'; keeps `key' for next iteration
    }

7 lua_rawgeti

    void lua_rawgeti (lua_State *L, int index, int n); 
    테이블을 배열로 사용하는 경우에 주로 사용하는 함수다. index 위치에 있는 테이블의 n 번째 원소의 값을 읽어와, 스택의 맨 위에다 푸쉬한다. 즉 다음의 구문과 같은 기능이다.
    lua_pushnumber(L, n); 
    lua_rawget(L, index);

8 lua_rawseti

    void lua_rawseti (lua_State *L, int index, int n); 
    테이블을 배열로 사용하는 경우에 주로 사용하는 함수다. index 위치에 있는 테이블의 n 번째 원소의 값을 스택의 맨 위에 있는 값으로 설정한 다음, 팝한다. 호출하기 전에 설정할 값을 푸쉬해야 한다.
    lua_pushnumber(L, value); 
    lua_rawseti(L, index, n);
    이는 결국 다음의 구문과 같다.
    lua_pushnumber(L, n); 
    lua_pushnumber(L, value);
    lua_rawset(L, index);




1 lua_getmetatable

    int lua_getmetatable (lua_State *L, int index); 
    해당 인덱스에 있는 아이템의 메타테이블을 가져와 스택에다 푸쉬한다. 정상적으로 동작한 경우에는 0이 아닌 값을 반환한다. 인덱스가 잘못되었거나, 아이템에 메타테이블이 없는 경우, 스택에 아무 것도 푸쉬하지 않고, 0을 반환한다.


2 lua_setmetatable

    int lua_setmetatable (lua_State *L, int index); 
    스택의 맨 위에서 테이블을 팝해, 그 테이블을 지정된 위치에 있는 아이템의 메타테이블로 설정한다. 즉 이 함수를 호출하기 전에 메타테이블로 사용할 테이블을 푸쉬해둬야한다. 무사히 설정한 경우에는 0이 아닌 값을 반환하고, 실패한 경우에는 0을 반환한다. 두 경우 모두 스택에 먼저 푸쉬된 메타테이블은 팝된다.
    // 새로운 테이블을 생성해,  
    // __index 메타메서드를 자기 자신으로 설정한다.
    lua_newtable(L);
    lua_pushstring(L, "__index");
    lua_pushvalue(L, -2);
    lua_settable(L, -3);

    // 위에서 생성한 테이블을 다른 테이블의 메타테이블로 설정한다.
    lua_setmetatable(L, some_where_other_table_exist);


Environment (환경변수 다루기)

1 lua_getfenv

    void lua_getfenv (lua_State *L, int index); 


2 lua_setfenv

    int lua_setfenv (lua_State *L, int index); 


1 lua_call(함수다루기)

    void lua_call (lua_State *L, int nargs, int nresults); 
    루아 함수를 호출한다. nargs는 함수 호출시 같이 주어지는 인자의 갯수이고, nresults는 해당하는 함수가 반환하는 반환값의 갯수이다. 함수 호출 이전에 함수 자체와 인수들을 스택에 푸쉬해 놓아야 한다.

    2개의 인자를 가지고, 1개의 반환값을 가지는 함수 호출 예제
    lua_State* L = ...

    lua_getglobal(L, "some_function_name");
    lua_pushnumber(L, arg1);
    lua_pushnumber(L, arg2);

    if (lua_call(L, 2, 1) != 0)
    {
    // need error handling here
    ...
    }

    int result = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    호출 전의 스택                       호출 후의 스택 
    +---------+
    | arg2 |
    +---------+
    | arg1 |
    +---------+ +---------+
    | func | | retval |
    +---------+ +---------+
    | ... | | ... |
    +---------+ +---------+


2 lua_pcall

    int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); 
    루아 함수를 호출한다. lua_call 함수와 마찬가지로 nargs는 함수 호출시 같이 주어지는 인자의 갯수이고, nresults는 해당하는 함수가 반환하는 반환값의 갯수이다. 함수 호출 이전에 함수 자체와 인수들을 스택에 푸쉬해 놓아야 하는 점도 같다.

    단 하나 틀린 점은 해당 함수를 실행하다가 에러가 발생한 경우, 실행할 함수를 지정할 수 있다는 점이다. 마지막 인수인 errfunc 값이 에러 처리 함수의 스택 인덱스이다. 에러 처리 함수를 지정하기 싫다면 그냥 0을 주면 된다.

    2개의 인자를 가지고, 1개의 반환값을 가지는 함수 호출 예제
    lua_State* L = ...

    lua_getglobal(L, "some_function_name");

    int errorfunc = lua_gettop(L); // 현재 스택의 꼭대기, 즉 방금 집어넣은 함수의 스택 인덱스를 가져온다.
    lua_getglobal(L, "_TRACEBACK"); // _TRACEBACK은 전역 함수로서 콜스택을 출력하는 함수다.
    lua_insert(L, errorfunc); // 호출하고자하는 함수 밑에다 _TRACEBACK 함수를 집어넣는다.

    lua_pushnumber(L, arg1);
    lua_pushnumber(L, arg2);

    if (lua_pcall(L, 2, 1, errorfunc) != 0)
    {
    // 에러가 발생한 경우, _TRACEBACK 함수가 호출된다.
    // 이 함수는 현재 콜스택을 스택의 제일 위에다 문자열로서 푸쉬한다.
    string errormsg = lua_tostring(L, -1);
    ...
    }

    int result = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    호출 전의 스택                       호출 후의 스택 
    +---------+
    | arg2 |
    +---------+
    | arg1 |
    +---------+ +---------+
    | func | | retval |
    +---------+ +---------+
    | errfunc | | errfunc |
    +---------+ +---------+
    주의할 점이 하나 있는데, 스택 모양에서도 알 수 있듯이 에러 처리 함수는 스택에서 제거되지 않는다. 그러므로 함수를 지정했다면, 반드시 이에 대한 처리를 해줘야한다. 위의 예에서는 호출할 함수 바로 밑에다 에러 처리 함수를 집어넣었으므로, 리턴값을 뽑아낸 다음, 에러 처리 함수를 뽑아내면 된다.
    int result = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    lua_pop(L, 1); // 에러 처리 함수를 제거한다.


3 lua_cpcall

    int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); 


4 lua_pushcclosure

    void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); 

1 lua_newthread (코루틴 다루기)

    lua_State *lua_newthread (lua_State *L); 
    새로운 스레드(코루틴)를 생성해서 스택의 최상위에다 푸쉬하고, 스레드 컨텍스트를 반환한다. 에러가 생긴 경우에는 NULL을 반환한다. 기본적으로 스레드는 중지(suspend)된 상태다.

    • 새로운 스레드는 기존 스레드와 전역 오브젝트들을 공유한다.
    • 새로운 스레드는 기존 스레드와는 별개의 런타임 스택을 가진다.
    • 새로운 스레드는 기존 스레드와는 별개의 전역 테이블을 가진다.

    전역 오브젝트들(전역 테이블에 존재하는 오브젝트들)은 스레드 생성시 복사된다. 즉 스레드를 생성한 시점에서는 이전 스레드와 모든 오브젝트가 동일하다. 하지만 이후에 오브젝트들을 변경할 시에는 두 개의 스레드는 독립적이다. 한쪽에서 변경을 해도 다른 쪽은 변경되지 않는다. C 쪽에서의 deep copy와 비슷한 개념이라고 보면 되겠다.

     <!> 스레드의 메인 함수는 이 함수가 아니라 lua_resume 함수를 통해 지정하게 된다. 아래쪽의 lua_resume 함수를 참고하기 바란다.
     <!> 5.0.2 이전 버전에는 lua_closethread 라는 함수로 스레드를 명시적으로 삭제했던 모양인데, 5.0.2 이후부터는 가비지 컬렉션으로 자동 처리된다.


2 lua_resume

    int lua_resume (lua_State *L, int narg); 
    해당 스레드의 동작을 재개한다. narg는 스레드 쪽으로 넘길 인수의 갯수로서, lua_resume을 호출하기 전에 푸쉬해둬야 한다.

    최초로 lua_resume을 실행하는 경우, 즉 스레드를 생성한 후 처음으로 실행하는 경우에는 스레드의 몸체가 될 함수를 인수들보다 먼저 푸쉬해둬야 한다. 이후부터는 그냥 인수들만 푸쉬하면 된다.
    최초로 호출하는 경우,       이후부터 호출하는 경우, 
    준비해야할 스택 준비해야할 스택
    +-------------------+
    | arg2 |
    +-------------------+ +-------------------+
    | arg1 | | arg2 |
    +-------------------+ +-------------------+
    | thread function | | arg1 |
    +-------------------+ +-------------------+
    | thread | | ... |
    +-------------------+ +-------------------+
    이 함수가 리턴하는 경우는 세 가지이다. 첫번째는 스레드 실행이 끝난 경우이고, 두번째는 lua_yield 함수를 이용해 스레드의 동작을 중지시킨 경우이다. 그리고 마지막은 에러가 발생한 경우다.

    케이스 리턴값 스택
    스레드 실행이 끝난 경우 0 스레드 메인 함수가 반환한 값이 들어가 있다.
    lua_yield를 호출한 경우 LUA_YIELD (1) lua_yield 함수에다 넘긴 인수들이 들어가 있다.
    에러가 생긴 경우 0 or 1이 아닌 값 에러 메시지만이 들어가 있다.


3 lua_yield

    int lua_yield (lua_State *L, int nresults); 
    루아 스레드는 외부에서 동작을 중지시키는 것이 불가능하다. 그러므로 이 함수는 루아에다 등록한 C 함수 내부에서 다음과 같은 형태로만 사용할 수 있다.
    return lua_yield(L, nresults); 
    왜 이런 식으로 밖에 사용할 수 없는지는, lua_resume 함수를 호출한 다음에 이 함수를 어디서 어떻게 호출할 것인지 찬찬히 생각해 보면 알 수 있을 것이다. nresult는 루아쪽으로 넘길 인수의 갯수로서, lua_yield를 호출하기 전에 푸쉬해둬야 한다.


4 lua_xmove

    void lua_xmove (lua_State *from, lua_State *to, int n); 
    스레드 간에 데이터를 교환하기 위한 함수다. from 스레드의 스택에서 n 개만큼의 아이템을 팝해서, to 스레드의 스택에다 푸쉬한다.


1 panic function (에러 핸들링)

    lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); 


2 lua_error

    void lua_error (lua_State *L); 


1 lua_pop (매크로)

    #define lua_pop(L,n) lua_settop(L, -(n)-1) 
    스택의 맨 위에 있는 아이템을 팝한다.


2 lua_pushcfunction

    #define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) 
    C 함수를 스택에다 푸쉬한다. 보다시피 upvalue의 갯수는 0이다.


3 lua_register

    #define lua_register(L,n,f) \ 
    (lua_pushstring(L, n), \
    lua_pushcfunction(L, f), \
    lua_settable(L, LUA_GLOBALSINDEX))
    C 함수를 등록한다. n 인수는 함수의 이름 문자열, f 인수는 함수 포인터다.


4 lua_getregistry

    #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) 
    레지스트리 테이블을 가져와 스택의 맨 위에다 푸쉬한다.


5 lua_setglobal

    #define lua_setglobal(L,s) \ 
    (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX))
    전역 변수의 값을 설정한다. 이 매크로를 수행하기 이전에 전역 변수에다 할당할 아이템을 스택에다 푸쉬해둬야 한다. 수행 후에는 이전에 푸쉬한 아이템이 팝된다.
    lua_pushstring(L, "I'm a value"); 
    lua_setglobal(L, "MyVariable");


6 lua_getglobal

    #define lua_getglobal(L,s) \ 
    (lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX))

'프로그램언어 > Lua' 카테고리의 다른 글

Lua 배열을 손쉽게  (0) 2008.07.22
C++ 함수를 lua에서 호출하는 방법  (0) 2008.07.22
Lua 기본 명령어  (0) 2008.07.22