
1. 개요
이 문서는 ARM 보드에서 동작하는 C 프로그램이 루아 스크립트를
호출하여 실행한 후 루아 스크립트에서 선언된 변수중 테이블 값을 가져 오는 방법을
기술 합니다.
이 문서에서는 다음과 같은 내용을 다룹니다.
* 루아 스크립트 라이브러리를 포함하는 C 컴파일 용 Makefile
* 루아 스크립트를 호출하고 값을 얻어 오는 C 샘플 main.c
* 호출 되는 루아 스크립트 run.lua
2. 실습 구성
다음과 같은 디렉토리 구성을 하였습니다.
/project/lua/sample_lua_arm/lua_include : LUA 헤더 파일 모음
/project/lua/sample_lua_arm/lua_lib : LUA 라이브러리 소스 모음
/project/lua/sample_lua_arm/lua_samples : 앞으로 진행할 강좌의 소스 들
3. 기본 샘플 구성
소스는 다음 디렉토리에 위치 합니다.
/project/lua/sample_lua_arm/lua_samples/040_get_table_value_from_script
이 디렉토리에는 다음과 같은 파일이 있습니다.
Makefile
main.c
run.lua
4. 소스들
Makefile
CROSS_PREFIX = arm-linux TARGET = app_run_lua TARGET_NFS = /nfs/lua
C_SRCS = C_SRCS += main.c
LUA_SRCS = run.lua
# LUA Support -- CORE C_SRCS += ../../lua_lib/lapi.c C_SRCS += ../../lua_lib/lcode.c C_SRCS += ../../lua_lib/ldebug.c C_SRCS += ../../lua_lib/ldo.c C_SRCS += ../../lua_lib/ldump.c C_SRCS += ../../lua_lib/lfunc.c C_SRCS += ../../lua_lib/lgc.c C_SRCS += ../../lua_lib/llex.c C_SRCS += ../../lua_lib/lmem.c C_SRCS += ../../lua_lib/lobject.c C_SRCS += ../../lua_lib/lopcodes.c C_SRCS += ../../lua_lib/lparser.c C_SRCS += ../../lua_lib/lstate.c C_SRCS += ../../lua_lib/lstring.c C_SRCS += ../../lua_lib/ltable.c C_SRCS += ../../lua_lib/ltm.c C_SRCS += ../../lua_lib/lundump.c C_SRCS += ../../lua_lib/lvm.c C_SRCS += ../../lua_lib/lzio.c
# LUA Support -- LIB C_SRCS += ../../lua_lib/lauxlib.c C_SRCS += ../../lua_lib/lbaselib.c C_SRCS += ../../lua_lib/ldblib.c C_SRCS += ../../lua_lib/liolib.c C_SRCS += ../../lua_lib/lmathlib.c C_SRCS += ../../lua_lib/loslib.c C_SRCS += ../../lua_lib/ltablib.c C_SRCS += ../../lua_lib/lstrlib.c C_SRCS += ../../lua_lib/loadlib.c C_SRCS += ../../lua_lib/linit.c
INCLUDES += -I. INCLUDES += -I/usr/local/include INCLUDES += -I/usr/$(CROSS_PREFIX)/include INCLUDES += -I../../include
INCLUDES += -I../../lua_include
LDFLAGS += -L../../lua_lib/ LDFLAGS += -L/usr/$(CROSS_PREFIX)/lib
LIBS = -lm
CFLAGS += $(INCLUDES) CFLAGS += -Wall -O2 -g
ARFLAGS = rs
#--------------------------------------------------------------------- CC = $(CROSS_PREFIX)-gcc AR = $(CROSS_PREFIX)-ar rc AR2 = $(CROSS_PREFIX)-ranlib RANLIB = $(CROSS_PREFIX)-ranlib LD = $(CROSS_PREFIX)-ld NM = $(CROSS_PREFIX)-nm STRIP = $(CROSS_PREFIX)-strip OBJCOPY = $(CROSS_PREFIX)-objcopy CP = cp MV = mv #--------------------------------------------------------------------
C_OBJS = $(C_SRCS:%.c=%.o)
%.o:%.c @echo "Compiling $< ..." $(CC) -c $(CFLAGS) -o $@ $<
all : $(TARGET) $(LUA_SRCS) cp $(TARGET) $(TARGET_NFS) cp $(LUA_SRCS) $(TARGET_NFS)
$(TARGET) : $(C_OBJS) $(CC) $(LDFLAGS) $(C_OBJS) -o $@ $(LIBS)
dep : $(CC) -M $(INCLUDES) $(C_SRCS) > .depend
clean: rm -f *.bak rm -f *.map rm -f *.o rm -f $(C_OBJS) rm -f $(TARGET) core
distclean: clean rm -rf .depend
ifeq (.depend,$(wildcard .depend)) include .depend endif
run.lua
print( "ENTER RUN.LUA" ) print( "BEGIN........." ) A = { V1=1, V2="HEY", V3=4 }; print( "A.V1 =", A.V1 ); print( "A.V2 =", A.V2 ); print( "A.V3 =", A.V3 ); print( "END........." )
main.c
#include <stdio.h> #include <string.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h>
#define LUA_FILENAME "run.lua"
int main( int argc, char **argv ) { lua_State *L = NULL; int error; int int_value; char *str_value; int len_value; int stack_enter; int stack_table; printf( "sample : C function call Lua Script \n" ); L = luaL_newstate(); luaL_openlibs(L); error = luaL_loadfile( L, LUA_FILENAME ) || lua_pcall ( L, 0,0,0 ); printf( "Enter C routine\n" ); if( error ) { printf( "%s\n", lua_tostring(L,-1)); lua_pop(L,1); exit(0); } stack_enter = lua_gettop(L); // <--- (1) printf( "ENTER STACK INDEX = %d\n", stack_enter ); lua_getglobal(L,"A"); // <--- (2) if( lua_istable(L,-1)) // <--- (3) { stack_table = lua_gettop(L); // <--- (4) printf( "TABLE STACK INDEX = %d\n", stack_table );
lua_pushstring( L, "V1" ); // <--- (5) lua_gettable(L,-stack_table); int_value = lua_tointeger( L, -1 ); // <--- (6) printf( "V1 = %d\n", int_value ); lua_pushstring( L, "V2" ); // <--- (7) lua_gettable(L,stack_table); str_value = lua_tostring ( L, -1 ); // <--- (8) printf( "V2 = %s\n", str_value );
lua_pushstring( L, "V3" ); // <--- (9) lua_gettable(L,stack_table); int_value = lua_tointeger( L, -1 ); // <--- (10) printf( "V3 = %d\n", int_value ); } else { printf( "A is not a table" ); } lua_settop(L, stack_enter ); // <--- (11)
lua_close(L); printf( "sample end\n" ); return 0; }
5 소스 설명
(1) 현재 스택 인덱스 값을 얻습니다.
이 값은 나중에 스택을 제거하기 위해서 저장해 둡니다.
(2) 테이블을 스택으로 복사해 옵니다.
루아 스크립트에서 정의된 내용을 C에서 사용하려면 항상
스택으로 복사해 와야 한다는 것을 기억해야 합니다.
(3) 스택에 옮겨진 값이 테이블인가를 검사합니다.
(4) 테이블이 옮겨진 인덱스를 얻어와 변수에 저장합니다.
테이블 스택위치는 테이블의 필드값을 얻을 때 항상
필요하므로 이렇게 저장해 놓으면 프로그램이 편해집니다.
(5) 얻고자 하는 테이블의 키를 스택에 넣습니다.
여기서는 V1 의 필드값을 얻기 위해서 입니다.
(6) 스택에 옮겨진 테이블에서 스택에 옮겨진 필드 키에
해당하는 필드 값을 얻어 옵니다.
(7) 스택에 옮겨진 필드값을 정수형으로 읽어 옵니다.
(8) 얻고자 하는 테이블의 키를 스택에 넣습니다.
여기서는 V2 의 필드값을 얻기 위해서 입니다.
(9) 스택에 옮겨진 테이블에서 스택에 옮겨진 필드 키에
해당하는 필드 값을 얻어 옵니다.
(10) 스택에 옮겨진 필드값을 문자열이 지정된 선두 주소를 얻어 옵니다.
(11) 얻고자 하는 테이블의 키를 스택에 넣습니다.
여기서는 V2 의 필드값을 얻기 위해서 입니다.
(12) 스택에 옮겨진 테이블에서 스택에 옮겨진 필드 키에
해당하는 필드 값을 얻어 옵니다.
(13) 스택에 옮겨진 필드값을 정수형으로 읽어 옵니다.
(14) 더이상 참조를 하지 않는다면 스택을 비웁니다.
5.1 스택의 변화 설명
각 단계별 스택의 상황을 표시하면 다음과 같습니다.
각 단계별 스택의 상황을 표시하면 다음과 같습니다. (2) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 1 | A TABLE | -1 <-- stack_table = 1 +------------------+
(5) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 2 | KEY = V1 | -1 +------------------+ 1 | A TABLE | -2 <-- stack_table = 1 +------------------+ (6) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 3 | 1(V1 VALUE) | -1 +------------------+ 2 | KEY = V1 | -2 +------------------+ 1 | A TABLE | -3 <-- stack_table = 1 +------------------+
(8) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 4 | KEY = V2 | -1 +------------------+ 3 | 1 (V1 VALUE) | -2 +------------------+ 2 | KEY = V1 | -3 +------------------+ 1 | A TABLE | -4 <-- stack_table = 1 +------------------+
(8) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 5 | "HEY" (V2 VALUE) | -1 +------------------+ 4 | KEY = V2 | -2 +------------------+ 3 | 1 (V1 VALUE) | -3 +------------------+ 2 | KEY = V1 | -4 +------------------+ 1 | A TABLE | -5 <-- stack_table = 1 +------------------+ (11) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 6 | KEY = V3 | -1 +------------------+ 5 | "HEY" (V2 VALUE) | -2 +------------------+ 4 | KEY = V2 | -3 +------------------+ 3 | 1 (V1 VALUE) | -4 +------------------+ 2 | KEY = V1 | -5 +------------------+ 1 | A TABLE | -6 <-- stack_table = 1 +------------------+
(12) 단계를 거치면 다음과 같은 스택 상태가 됩니다. | | +------------------+ 7 | 1 (V1 VALUE) | -1 +------------------+ 6 | KEY = V3 | -2 +------------------+ 5 | "HEY" (V2 VALUE) | -3 +------------------+ 4 | KEY = V2 | -4 +------------------+ 3 | 1 (V1 VALUE) | -5 +------------------+ 2 | KEY = V1 | -6 +------------------+ 1 | A TABLE | -7 <-- stack_table = 1 +------------------+ (14) 단계를 거치면 다음과 같은 스택 상태가 됩니다. + + | | 0 +------------------+ 0
6. 결론
루아 스크립트에 선언된 테이블 변수를 얻어 올때는
1) lua_getglobal() 함수를 이용하여 스택으로 값을 복사합니다.
2) 루아 스크립트에 선언된 테이블 내의 필드 값을 얻어 올때는
lua_pushstring() 함수를 이용하여 스택에 얻고자 하는 필드 키 값을
넣고
lua_gettable() 함수를 이용하여 스택에 필드 값을 복사해 오도록 합니다.
lua_toXXX() 계열의 함수를 이용하여 C 에서 사용할수 있는
변수로 변환 합니다.
꼭 기억 할것은 C에서 참조하려면 스택에 해당 값이 루아에서
복사해 와야 하고
스택에서 제거되면 해당 참조나 변환이 불가능합니다.
그러므로 스택에서 값을 가져온후 스택에 내용을 제거한 후에도
계속 참조하려면
C 에 따로 버퍼나 변수값을 만들고 복사해서 사용해야 합니다.
7 수행 예
다음은 보드에서 수행한 예 입니다.
[root@falinux nfs]$ ./app_run_lua
sample : C function call Lua Script
ENTER RUN.LUA
BEGIN.........
A.V1 = 1
A.V2 = HEY
A.V3 = 4
END.........
Enter C routine
ENTER STACK INDEX = 0
TABLE STACK INDEX = 1
V1 = 1
V2 = HEY
V3 = 4
sample end
[root@falinux nfs]$