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/030_get_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 = 1234
B = "Hey"
print( "A =", A );
print( "B =", B );
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;
    
    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 )                                     
    {
        fprintf(stderr,"%s\n", lua_tostring(L,-1)); 
        lua_pop(L,1);                               
    }
    
    lua_getglobal(L, "A" );                     // <---  (1)
    lua_getglobal(L, "B" );                     // <---  (2)
    
    int_value = lua_tointeger( L, 1  );         // <---  (3)
    printf( "A = %d\n", int_value );    
    int_value = lua_tointeger( L, -2 ); 
    printf( "A = %d\n", int_value );    
    str_value = lua_tostring ( L, 2  );         // <---  (4)
    printf( "B = %s\n", str_value );    
    str_value = lua_tostring ( L, -1 ); 
    printf( "B = %s\n", str_value );    
    
    str_value = lua_tolstring( L, 2, &len_value  ); // <---  (5)
    printf( "B = %s length = %d\n", str_value, len_value ); 
    
    lua_settop( L, 0 );                         // <---  (6)
    
    lua_close(L);                                   
    
    printf( "sample end\n" );                   
    return 0;
}

5 소스 설명

 

(1) 루아 스크립트에서 선언되어 있는 A 변수를 사용하기 위해서 스택으로 이동시킵니다.
(2) 루아 스크립트에서 선언되어 있는 B 변수를 사용하기 위해서 스택으로 이동시킵니다.

(1) 과 (2) 과정을 거치면 다음과 같이 루아 값이 스택으로 옮겨 집니다.

 

       |                  |
       +------------------+
   2   |        B         | -1
       +------------------+
   1   |        A         | -2
       +------------------+
      
 
(3) 스택의 1 번 위치와 -2 는 위 스택구조로 보면 동일한 위치를
    가리키고 해당 위치에 있는 값이 어떤 값이든 상관없이
    정수로 바꾸어 옵니다.

(4) 스택의 2 번 위치와 -1 는 위 스택구조로 보면 동일한 위치를
    가리키고 해당 위치에 있는 값이 어떤 값이든 상관없이
    문자열로 얻어 옵니다.

(5) 스택에 있는 값을 문자열로 변환해서 얻어 올 때
    문자열에 길이까지 알고 싶다면 lua_tolstring() 함수를
    사용해야 합니다.
   
(6) 더 이상 참조하지 않으면 스택으로 복사된 내용을 모두 제거 합니다.   
 
6. 결론

 

루아 스크립트에 선언된 변수를 얻어 올때는
 
1)  lua_getglobal() 함수를 이용하여 스택으로 값을 복사합니다.
2)  lua_toXXX() 계열의 함수를 이용하여 C 에서 사용할수 있는
     변수로 변환 합니다.
    
꼭 기억 할것은 C에서 참조하려면 스택에 해당 값이 루아에서
복사해 와야 하고
스택에서 제거되면 해당 참조나 변환이 불가능합니다.

그러므로 스택에서 값을 가져온후 스택에 내용을 제거한 후에도
계속 참조하려면
C 에 따로 버퍼나 변수값을 만들고 복사해서 사용해야 합니다.
  

7 수행 예

 

다음은 보드에서 수행한 예 입니다.
 
[root@falinux nfs]$ ./app_run_lua
sample : C function call Lua Script
ENTER RUN.LUA
BEGIN.........
A =     1234
B =     Hey
END.........
Enter C routine
A = 1234
A = 1234
B = Hey
B = Hey
B = Hey length = 3
sample end
[root@falinux nfs]$