C000_lua.gif

 

1. 개요

 

    이 문서는 ARM 보드에서 동작하는 루아 스크립트에서 C 함수를 호출하는 방법을 기술 합니다.
   
    루아 스크립트에서 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/080_lua_pcall_error
    
     이 디렉토리에는 다음과 같은 파일이 있습니다.
    
     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( "call c function from lua script" )
c_sample_function();
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 c_sample_function( lua_State *L )
{
 printf( "Enter c_sample_function\n" );
 printf( "Exit c_sample_function\n" );
 return 0;
}
int main( int argc, char **argv ) 
{
 lua_State  *L = NULL; 
 int   error;
 printf( "sample : call c function from lua\n" );
 L = luaL_newstate();       
 luaL_openlibs(L);        
 lua_pushcfunction(L,c_sample_function ); // <<-- (1)
 lua_setglobal(L, "c_sample_function" );  // <<-- (2)
 error =  luaL_loadfile( L, LUA_FILENAME ) // <<-- (3) 
       || 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);
 }
 lua_close(L);
 printf( "sample end\n" );          
 return 0;
}

 


5 소스 설명

 

 (1) 루아 스크립트에서 호출될 함수 c_sample_function()를 lua_pushcfunction()함수를 이용하여
     스택에 밀어 넣습니다.
 (2) 스택에 있는 함수를 루아 스크립트에서 호출할수 있도록 만듭니다.
 (3) 루아 스크립트를 호출 합니다. 이후 루아 스크립트에서
       c_sample_function() 를 호출하게 됩니다.

 

5.1 스택의 변화 설명

 

    각 단계별 스택의 상황을 표시하면 다음과 같습니다.

   
 (1) C 함수를 스택에 넣은 상태입니다.
 
        |                    |
        +--------------------+
    1   |  c_sample_function | -1
        +--------------------+

 

 (2) lua_setglobal() 함수를 호출하여 c_sample_function() 함수가 전역화 되면서 제거 됩니다.

 

        |                    |
        +--------------------+
       
6. 결론

 

    루아 스크립트에서 C 함수를 호출하려면
   
    1)  루아 스크립트를 로드하고 실행하기 전에
    2)  lua_pushcfunction()를 사용하여 스택에 넣은 후
    3)  lua_setglobal()를 사용하여 호출 가능하게 만들어야 합니다.

 

7 수행 예

 

 다음은 보드에서 수행한 예 입니다.
 
[root@falinux nfs]$ ./app_run_lua
sample : call c function from lua
ENTER RUN.LUA
call c function from lua script
Enter c_sample_function
Exit c_sample_function
END.........
Enter C routine
sample end
[root@falinux nfs]$