2015. 9. 20. 23:39ㆍ프로그래밍/Script
스택 이해하기
C와 lua간 연동에 중요한 요소는 가상 스택이다.
lua의 스택 액세스 방법은 절대/상대 접근이 있다.
양수 값 - 절대 접근
음수 값 - 상대 접근
절대 접근 방법은 스택 base에서 시작해 양수 1,2,3으로 순서를 부여하는 방법이다.
상대 접근 방법은 스택 top에서 시작해 음수 -1,-2,-3으로 순서를 부여하는 방법이다.
*스택의 마지막 값을 접근 시 -1, 바닥부터 접근 시 1
lua_checkstack : 스택 사이즈를 확인하기 위한 lua C API
LUA_MINSTACK 20 으로 정의
허용 가능한 스택 인덱스 범위는
1 | (index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace ) | cs |
글로벌 테이블의 의사인덱스 : LUA_GLOBALSINDEX
Lua에서 C 함수 호출
순서
C함수 정의 - C함수 lua에 등록 - lua에서 등록된 함수 호출
우선 Visual Sutdio랑 연동(VS2012)
https://code.google.com/p/luaforwindows/downloads/detail?name=LuaForWindows_v5.1.4-46.exe&can=2&q=
에서 luaforwindows 설치
cmd에서 lua를 이용할 수 있다.
버전에 맞는 루아 바이너리 받기
난 VS2012용 정적 라이브러리를 받았다.
디렉토리 지정과 추가종속성 지정에 대한 설명은 생략한다.
예제
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | extern "C" { #include "lua.hpp" } // 함수 정의 int luaHello(lua_State* L) { int count = 0; // luaL_checkstring을 통해 루아에서 넘어온 값을 가져온다. // 양수 1은 stack base의 첫 번째 값으로 루아에서 넘어온 첫 인자. const char* name = luaL_checkstring(L, 1); count++; printf("%s\n", name); // test name = luaL_checkstring(L, 2); count++; printf("%s\n", name); return count; } // 메인 void main() { lua_State *lua = luaL_newstate(); luaL_openlibs(lua); // 함수 등록하기 lua_register(lua, "hello", luaHello); // hello.lua에서 읽기 luaL_dofile(lua, "hello.lua"); // 루아 닫기 lua_close(lua); } | cs |
hello.lua
1 2 | hello("alice", "vorpal sword") hello("hello", "kowabunga!") | cs |
이게 말이 좀 애매해서 한참을 봤다.
C에서 정의한 함수를 루아 스크립트만 돌렸을 때는 당연히 안되고
컴파일 했을 때 루아에 있는 스크립트에서 C 함수가 작동된다는 말... 참 한글 어렵죠.
C에서 lua 함수 호출하기
lua 함수를 스택에 올림 - 스택에 있는 함수를 실행
lua 함수 스택에 올리기
1 2 3 4 5 6 7 8 9 | //case1) lua_pushstring("function"); lua_gettable(lua, LUA_GLOBALSINDEX); //case2) lua_getfield(lua, LUA_GLOBALSINDEX, "function"); //case3) lua_getglobal(lua, "function"); | cs |
세 가지중 하나로. LUA_GLOBASINDEX를 5.2버전에서는 사용할 수 없다고 한다.
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #include <string> extern "C" { #include "lua.hpp" } // 함수 정의 int luaHello(lua_State* L) { int count = 0; // luaL_checkstring을 통해 루아에서 넘어온 값을 가져온다. // 양수 1은 stack base의 첫 번째 값으로 루아에서 넘어온 첫 인자. const char* name = luaL_checkstring(L, 1); count++; printf("%s\n", name); // test name = luaL_checkstring(L, 2); count++; printf("%s\n", name); return count; } // 메인 void main() { // 초기화 lua_State *lua = luaL_newstate(); luaL_openlibs(lua); // 루아에서 C함수 사용하기 // 함수 등록하기 lua_register(lua, "hello", luaHello); // hello.lua에서 읽기 luaL_dofile(lua, "hello.lua"); lua_getglobal(lua, "popura"); if (lua_isfunction(lua, -1) == false) { fprintf(stderr, "print is not function\n"); return; } // C에서 루아 함수 사용하기 // 스택 탑 구하기 int top = lua_gettop(lua); lua_getglobal(lua, "popura"); if (lua_isfunction(lua, -1) == false) { return; } // pcall 에러 핸들러 int handle = lua_pcall(lua, 0, LUA_MULTRET, 0); if (handle) { fprintf(stderr, "call error: %s\n", lua_tostring(lua, -1)); return; } int ret_cnt = lua_gettop(lua) - top; printf("ret_cnt = %d\n", ret_cnt); int ret_val1 = 0; std::string ret_val2; // 스택 탑에서 문자값 가져오기 ret_val2 = luaL_checkstring(lua, -1); // 스택 팝 lua_pop(lua, 1); // 스택 탑에서 숫자값 가져오기 ret_val1 = static_cast<int>(luaL_checknumber(lua, -1)); // 스택 팝 lua_pop(lua, 1); // 루아에서 가져온 값 출력 printf("%d, %s", ret_val1, ret_val2.c_str()); // 루아 닫기 lua_close(lua); } | cs |
hello.lua
1 2 3 4 5 6 | function popura() return 1, "popura" end hello("alice", "vorpal sword") hello("hello", "kowabung") | cs |
결과
'프로그래밍 > Script' 카테고리의 다른 글
[Lua, Json] lua에서 json 처리하기. json for lua (3) | 2016.01.15 |
---|---|
[루아] Lua에서 .과 :의 차이(?) + OOP (4) | 2015.12.17 |
개론 (2) | 2015.10.01 |
Lua 메타테이블 (0) | 2015.09.20 |
Lua 5.x와 4.0 호환성 (0) | 2015.09.20 |
Lua 조건문, 반복문 (0) | 2015.09.19 |
Lua 연산자 (0) | 2015.09.19 |