블로그는 나의 힘!
[ Programing ]/Lua Scirpt2022. 3. 6. 01:08

앞의 정리 08. C++과 연동에서 연동에 필요한 기본적인 것들에 대해서 알아 보았습니다.
지금의 예제는 제한된 기능의 루아 콘솔 프로그램 입니다.

GAME DEVELOPMENT with LUA에서 처음으로 나오는 연동 예제 입니다.

 

실력이 모자란 관게로 처음 이 예제를 봤을 때 이게 뭐고 라고 생각했습니다.
그래도 여러번 보게 되니깐 대충은 이해가 가더라고염 ~.~;;

일단 전체 소스 코드를 먼저 올리고 그 후 각 부분에 대해서 설명 하겠습니다.

 

=======  제한된 루아 콘솔 프로그램 =======

// 시스템 헤더 포함
#include <stdio.h>
#include <string.h>

/*
** 루아 헤더 포한
** 루아 헤더들은 C로 되어 있다. 그런데 이것은 C++ 프로그램이기 때문에,
** 루아 헤더들에 담긴 정의들이 C로 굍 것이고 따라서 C++ 이름 섞기를
** 적용하지 말아야 한다는 점을 C++ 컴파일러에게 알려 주어야 한다.
** extern "C"가 바로 그런 의미이다.
*/
extern "C" {
     #include <lua.h>
     #include <lualib.h>
     #include <lauxlib.h>
}

/*
** 루아글루 함수의 예이다.
** 이 함수는 루아에서 호출 한다.
** 루아는 ANSI C로 작성된 것이므로, 앞에서와 마찬가지로
** extern "C"를 지정해서 C++ 이름 섞기를 방지 한다.
*/
extern "C" int _Version(lua_State *L)
{
     puts("This is Version 1.0 of the Console Program");
     puts(LUA_VERSION);
     puts(LUA_COPYRIGHT);
     puts(LUA_AUTHORS);
     return 0;
}

/*
** 루아 환경에 등록할 루아글루 함수들의 정보
** 이후 루아 API를 이용해서 이들을
** 실제로 루아 환경에 등록한다.
*/
static luaL_reg ConsoleGlue[] =
{
     {"Version",  _Version},
     {NULL, NULL}
};

char gpCommandBuffer[254];

const char *GetCommand(void)
{
     printf("Ready> ");
     return gets(gpCommandBuffer);
     puts("\n");
}

void main(void)
{
     puts("Lua Console (basic) (c) 2004 Charles River Media");
     puts("Enter Lua commands at the prompt, [QUIT] to exit\n\n");

     // 루아 환경 생성 및 설정
     lua_State *pLuaState = lua_open();
     luaopen_base(pLuaState);
     luaopen_io(pLuaState);
     luaopen_string(pLuaState);
     luaopen_math(pLuaState);
     luaopen_debug(pLuaState);
     luaopen_table(pLuaState);

     // 루아 글루 함수 등록
     for(int i=0; ConsoleGlue[i].name; i++)
     {
           lua_register(pLuaState, ConsoleGlue[i].name, ConsoleGlue[i].func);
     }

     // 명령 처리
     const char *pCommand = GetCommand();
     while(stricmp(pCommand, "QUIT") != 0)
     {
          // 문자열을 루아 환경에 적재, 구문 점검, 실행가능 형태로 준비
          if (luaL_loadbuffer(pLuaState, pCommand, strlen(pCommand), NULL) == 0)
     { 
          // 실행 가능 상태이면 실행
          if(lua_pcall(pLuaState, 0, LUA_MULTRET, 0) != 0)
          {
               // 명령 실행 실패
               printf("ERROR:%s\n", luaL_checkstring(pLuaState, -1));
          }
     }
     else
     {
          // 명령 읽기 실패
          printf("ERROR:%s\n", luaL_checkstring(pLuaState, -1));
     }
          // 다음 명령 가져 오기
         pCommand = GetCommand();
     }
     lua_close(pLuaState);
}

 

※ 색상의 구분이 안되어서 불편 하군요~ 그래도 일일이 다하기는 귀찮고해서 그냥 주석 부분만 처리 했습니다.

 

=======  예제에 대한 설명 =======

1. 시스템 헤더 포함 

이 부분은 설명 하지 않겠습니다. 필요한 헤더 파일을 추가 하면 되겠지요~~

 

2. 루아 헤더 포함

루아 API에 관련된 함수들의 헤더 파일 입니다. 각각의 헤더 파일의 자세한 기능은 아직 저도 모릅니다.

나중에 알게 되면 변경 하도록 하고 
여기서 중요한건 주석에도 나와 있는 C++ 이름 섞기 방지를 해야 한다는 것 입니다.

 

3. 루아 글루 함수

루아 글루 함수의 의미는 앞에서도 설명 했기 때문에 생략하도록 하고요. 
지금의 루아 글루 함수 int _Version( lua_State* L) { } 함수는 단순한 루아 버전 정보를 출력하는 함수 입니다.

이 함수를 호출하는 부분은 이 예제 소스에는 나와 있지 않습니다만,
예제가 콘솔 프로그램 이기 때문에 출력 해보는 것은 어렵지 않습니다.
우선 루아 스크립트 파일을 하나 만듭니다.

파일명을 D:\\lua_scr\\console_test.lua로 만들고, 
안의 내용을 Version()으로 만든 후에 최종적으로 루아 콘솔 프로그램 예제를 실행 시킨 후 

Ready > dofile("D:\\lua_scr\\console_test.lua")  ↙
하면 루아 글루 함수 _Version() 이 호출되어 루아 버전 정보를 화면에 출력 하게 된다.

 

4. 루아 환경 등록을 위한 정보 관리

lua_reg 변수 안에 { "lua_name", C++_name } 쌍으로 들어가게 된다.

C++_name이 실제로 C++에서 작성한 루아 글루 함수의 이름이고, 
"lua_name"은 루아 스크립트 환경에서 루아 글루 함수를 호출 할때 사용 되는 이름 입니다.

 

5. 명령을 받는 일반 함수

C++ 상에 gets()함수를 이용하여 입력한 문자열을 gpCommandBuffer에 담은 다음 반환 하는 함수.

이 함수 반환하는 gpCommandBuffer에 루아 스크립트 명령(청크)가 들어가게 되면, 
루아 API로 이를 분석하여 처리 하게 된다.

 

6. 루아 환경 생성 및 설정

루아 환경은 lua_open()으로 생성하며, 이 함수가 반환값을 이용하여 루아 환경을 설정하게 된다.
필요한 부분만 설정 하면 된다.

 

7. 루아 글루 함수 등록

루아 글루 함수는 lua_register()로 등록 된다.
인자로 '루아 환경 변수', '스크립트에서의 이름',' C++에서의 함수'를 받는다.

 

8. 명령 처리 부분

명령 처리 부분에서는 루아 API를 이용하여 C++에서 루아 스크립트(루아 함수)를 사용할 수 있게 한다.

이 예제 프로그램이 루아 콘솔 프로그램 이므로 우리가 입력한 명령들을 루아 환경에 적재하고 
적합한 구문 인지를 점검하여 실행 가능한 형태로 바꾸는 함수가 lua_loadbuffer()이다.

여기에 들어가는 인자 중 pCommand가 루아 스크립트에서 작성한 함수라 그 함수의 적합성을 판단하여
실행가능한 형태로 만든 것이다. 
(이 프로그램에서 실행 가능한 형태가 되기 위해서는 이전에 
 dofile로 먼저 해당 함수를 포함한 루아 스크립트 파일을 호출하는것이 필요 할 것이다.)

그리고 그것을 실제로 실행하는 기능을 하는 함수가 lua_pcall() 함수 이다.
lua_pcall()함수가 루아 스택에서 해당 명령을 가져와서 실행을 하게 된다.

실행 여부가 만약 실패하게 되면, 오류 메시지를 남기는데 이 메시지 출력 하는 함수가 luaL_checkstring()함수 이다.

 

9. 루아 환경 해제

루아 환경을 생성 했으면, 필요 없을 시에는 lua_close() 함수로 해제 한다.

 

※ 설명 중간 중간 제가 추측하여 정리한 부분이 있어서 설명이 틀릴수 있을 지도 모르겠네요~
   이부분 양해 바랍니다.

    제가 실제로 해본 부분은 현재 여기까지 입니다.
    이 후로 실제로 루아 스크립트 내부의 함수를 C++에서 호출하고 그 반환값을 활용하는 방법과
    루아 글루 함수를 루아 스크립트 내부에서 호출하고 그 반환값을 활용하는 방법에 대해 학습을 하고
    정리해서 올릴까 합니다. ^^*

 



[출처] Lua - 09. 간단한 예제|작성자 악마



 

Posted by Mister_Q
[ Programing ]/Lua Scirpt2022. 3. 6. 00:57

루아를 공부하면서 가장 힘들었던 부분이 C++과 연동하는 부분이 었습니다.
아직 초보 프로그래머라서 그런지 인터넷으로 루아 배포판을 다운받고

교재를 따라 코딩을 하였는데 엄청난 오류와 경고들 ㅠㅠ
인터넷을 뒤져봐도 어떻게 처리 해야되는지 잘 나와 있지 않더군여.... (내가 못찾았나 ㅠㅠ)

연동하는 프로그램을 작성 하기 이전에 기본적인 설정을 해야 합니다.

이 부분을 몰라서 많이 헤맨거죠 ㅡ.ㅡ;;

 


======= 루아 배포판의 기본적인 설정 =======

1. 우선 루아 배포판을 다운 받는다.

http://www.lua.org/ftp/ 

lua-5.0.2를 다운을 받고 D:\\lua-5.0.2폴드로 압출을 풀었음.
(참고 : 루아는 사장된 언어로 다음 버전 없음)


 

2. 루아 소스 파일들을 정적라이브러리로 만든다.

루아소스 전부를 매번 프로젝트를 만들때마다 추가 시켜 주어도 되지만 많이 번거럽고 변경 사항에 유동적이지
못하기 때문에 정적라이브러리로 만듭니다.
    
한번 만들어 놓으면 다음에 사용할 경우는 

프로젝트 속성에서 링커 -> 추가 종속성 -> lua.lib(경로포함) 를 입력하고
 
프로젝트 속성에서 C/C++ -> 추가 포함 디렉터리 ->
D:\\lua-5.0.2\\include(루아 소스 경로)를 입력하면 됩니다.

   

   << 만드는 방법 >>

   비주얼 스튜디오 2005를 사용하기 때문에 그것을 기초로 설명 하겠습니다.

   새 프로젝트 -> Win32 콘솔 응용 프로그램 -> 정적 라이브러리 -> 빈 프로젝트로 프로젝트를 생성한다.
   생성된 프로젝트에서 루아 배포판의 소프 파일들을 추가 한다.

   D:\\lua-5.0.2\src와 D:\\lua-5.0.2\src\lib 폴드 안의 모든 소스들...
   보기 좋게 하기위해 기존의 리소스, 소스, 헤더 필터들은 지워 버리고 lua로 새로운 필트를 만들어 추가한다.

   프로젝트 속성에서 C/C++ -> 추가 포함 디렉터리 -> D:\\lua-5.0.2\\include(루아 소스 경로)를 입력하고
   프로젝트를 컴파일한다. 그러면 debug폴드에 lua.lib 파일이 생성된다.

 

3. 실제 프로젝트에서 루아 라이브러리를 추가 한다.

실제 작업할 프로젝트를 생성한 후 
프로젝트 속성에서 C/C++ -> 추가 포함 디렉터리 -> D:\\lua-5.0.2\\include(루아 소스 경로)
를 입력하고 프로젝트 속성에서 링커 -> 추가 종속성 -> lua.lib를 입력(경로 포함) 한다.

     

 

======= 루아와 C++의  연동 =======

루아와 C++를 연동하기 위해서 기본적으로 루아 환경, 루아 글루 함수, 루아 API에 대해서 알아야 한다.

이것들의 개념을 간단히 짚어보고 넘어 갈까 합니당~~

 

1. 루아 환경 ( 루아 상태[Lua state])

루아의 실행에 필요한 모든 자료(컴파일된 함수, 변수, 기타 작업용 메모리)로 구성된다.
그 자료는 lua_State라고 하는 구조체에 저장된다.

C++로 작성된 호스트 코드에서는 루아 환경을 루아에 자료를 보내거나 루아로부터 자료를 받는 수단으로 사용한다. 

모든 자료 전달은 루아가 관리하는 스택을 거치며, 루아 API 함수로 접근하는 루아 스택은 시스템
스택과는 무관한, 루아가 직접 관리하는 스택이다.

실질적으로 루아와 C++을 연동하여 자료들을 공유 할경우는 루아 스택에서 자료를 push, call 해야 한다.

루아 스택에 관해서는 나중에 다시 언급 할 것 입니다.

 

2. 루아글루 함수

C++로 작성된 함수를 루아 스크립트 안에서 호출할 수 있는데, 그런 함수를 루아 글루 함수라고 한다.
그런 함수가 C++ 세계를 루아 환경과 연결하는 '접착제(glue)' 역할을 한다.

보통 루아 함수와 동일하더라고 실제로는 C++로 만들어진 것이므로, C++ 프로그래머가 사용할 수 있는 모든
자원에 접근할 수 있다는 점에서 보토의 루아 함수와 구별된다.

루아 글루 함수는 루아 스크립트에서 C++ 자료를 읽고, 수정하고, C++ 고유의 함수를 실행할 수 있는 수단이다.

 

3. 루아 API

루아에서 정의된 함수를 C++ 코드에서 직접 실행하는 수단을 제공 한다.
루아 API는 문자열 형태로 된 루아 코드를 루아 인터프리터에 넘겨주고 그것을 실행하는 수단도 제공 한다.

 

※ 실제 연동은 다음의 정리 - 간단한 예제(링크)를 이용하여 설명~ ^^* 

 



 

Posted by Mister_Q
[ Programing ]/Lua Scirpt2022. 3. 6. 00:46

1. assert(청크)()
 -. 컴파일된 루아 스크립트 청크를 하나의 처리 함수처럼 실행할 수 있도록 하는 수단.
 -. 청크는 하나의 명령 또는 일련의 명령들로, 크기에 제한이 없음.
 -. loadstring, loadfile 함수로도 청크를 적재, 컴파일 가능 함.
 -. loadstring으로도 임의의 청크를 실행할 수 있지만, 오류 메시지를 표시 하지 못 함.
 -. loadfile은 dofile이 더 유용하기 때문에 거의 사용 하지 않음.
 -. assert(loadstring(string))()을 이용하여 유용하게 사용 가능.

 ex)
 a = "hello word"
 b = "print(a)"

 assert(loadstring(b))()
 hello world




2. dofile(파일이름)
 -. 파일을 적재하고 즉시 처리.

 ex)
 dofile("scripts/runtime_functions.lua");
  <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

<< 수학 함수들>>

math.abs math.acos math.asin math.atan
math.atan2 math.ceil math.cos math.deg
math.exp math.floor math.log math.log10
math.max math.min math.mod math.pow
math.rad math.sin math.sqrt math.tan
math.frexp math.ldexp math.random math.randomseed

* math.pi : 원주율 값을 담고 있음.


 

3. math.floor()
 -. 주어진 수의 소수부를 버리고 정수로 변환.
 -. 반올림이 필요하면 +0.5 함.

 ex)
 a = 5.125
 b = 5.75

 a = a + 0.5
 b = b + 0.5

 a = math.floor(a)     --!< a = 5
 b = math.floor(b)     --!< b = 6


 

4. math.ceil()
 -. 주어진 수의 소수부를 올리고 정수로 변환.
 

 ex)
 a = 5.125
 b = 5.75
 a = math.ceil(a)     --!< a = 6
 b = math.ceil(b)     --!< b = 6




  

5. math.random()
 -. 난수 발생 함수.
 -. 인자값을 주지 않으면 0~1 사이의 의사난수를 돌려줌.
 -. 인자 값으로 범위를 정함 : 범위안에 정수 난수를 돌려 줌.

 ex)
 myDie = math.random(1,6)

 -. 더 무작위 값을 얻기위해 종자값 함수 사용.

 ex)
 math.randomseed(os.data("%d%H%M%S"))     --!< 날짜함수 유용.




6. math.max(), math.min()
 -. 어떤 집합에서 가장 큰 값과 가장 작은 값을 찾아 냄.

   
  

7. tonumber()
 -. 문자열을 수치로 변환.

 ex)
 mySting = "1234"
 myNum = tonumber(mySting)
 print(myNum + 2)     --> 1236


 

8. tostring()
 -. 수치를 문자열로 변환.

 ex)
 myNum = 1234
 myString = tostring(myNum)
 print(type(myString))     --> "string"




9. string.char(n1, n2, ...)
 -. 주어진 수치 인수들을 ASCII 값들로 해석하고, 
    그 ASCII 값들에 해당한는 문자들로 하나의 문자열을 만들어서 돌려 줌.

 ex)
 myFile:write(string.char(10))     --!< 열린 파일에서 줄 바꿈.

 


10. string.len(myString)
 -. 문자열의 개수 반환.

 ex)
 myString = "1234"
 print(string.len(myString))     --> 4




11. string.sub(myString, start, end)
 -. 문자열 안의 한 부분을 돌려줌, start~end 사이.

 ex)
 myString = "hello world"
 newString = string.sub(myString, 1, 5)
 print(newString)     --> "hello"

 -. start, end는 음수 값도 가능하며, 끝을 기준으로 함.
 -. end는 생략시 문자의 끝으로 간주.

 


12. string.format()
 -. 문자열읠 포매팅하는 함수로, 여러 변수들의 값을 포함하는 문자열을 만들 때 편리 함.

 ex)
 myName = "Jungho"
 myIQ = 80
 myString = string.format("%s%s%d%s", myName, "'s IQ is ", myIQ, ".")
 print(myString)

 * 루아는 문자열 연결 연산자(..)를 제공




13. string.find(sourceString, findString)
 -. 첫 번째 인수로 주어진 원본 문자열에서 두 번째 인수로 주어진 대상 문자열이 
    처음 나타난 부분의 시작과 끝 위치를 돌려 줌.
 -. 없을 경우는 nil을 반환.

 ex)
 mySting = "My name is John Smith."
 sStart, sEnd = string.find(myString, "John")
 print(sStart, sEnd)     --> 12 15



<< 문자열과 패턴 >>

 -. 패턴이란 루아가 문자열로부터 의미 있는 결과를 걸러내도록 하는 일종의 틀이라고 할 수 있음.
 -. 루아의 패턴을 만든는 데 쓰이는 요소들.

. 모든 문자 %s 공백 문자
%a 영문자 %u 영문 대문자
%c 제어문자 %w 영수문자
%d 숫자 %x 16진수 숫자
%l 영문 소문자 %z 코드 값 0에 해당하는 숫자
%p 문장부호

 
 


14. string.gsub(sourceString, pattern, replacementString)
 -. 문자열에서 pattern에 부합하는 부분을 replacementString으로 주어진 문자열로 치환.

 ex)
 myString = "Tel : 555-3257"
 newStr= string.gsub(myString, "%d", "*")
 print(newStr)     --> Tel : ***-****


 

15. string.gfind(sourceString, pattern)
 -. 첫 번째 인수로 주어진 문자열에서 두 번째 인수로 주어진 패턴을 한 번에 하나씩 차례로 찾아 나감.

 ex)
 myString = "This is my rather long string."
 print(myString)

 counter = 1

 for myWord in string.gfind(myString, "%a+") do
     print(string.format("Word #%d : %s", counter, myWord))
     counter = counter + 1
 end

 -. %a+는 빈칸이나 문장부호, 숫자 등이 나오기 전까지의 임의의 개수의 영문자들을 의미 함.

 

 

16. table.getn(myTable)
 -. table의 요소 개수를 돌려 줌.

 ex)
 for index=1, table.getn(myTable) do
     print(myTable[index])
 end


 

17. table.sort(myTable [, comp])
 -. table의 요소들을 크기를 비교하여 comp에 따라 정렬 함.

 ex)
 function Sort(theTable, direction)
     if direction ~= 1 then
         table.sort(theTable)     --!< 오름 차순 정렬
     else
         function Reverse(a, b)     --!< 반전 함수 정의
             if a<b then
                 return false
             else
                 return true
                 end
             end
         table.sort(theTable, Reverse)     --!< 반전 함수 값의 따라
     end     --!< 정렬 : 내림차순
end  




18. table.insert(myTable, position, value)
 -. table에 새 요소를 추가.
 -. position 인수를 생략하면 table 끝에 추가.

 ex)
 table.insert(myTable, 25, “hello")




19. table.remove(myTable, position)
 -. table에서 특정 요소를 제거하고 그 요소를 돌려 줌.

 ex)
 print(table.remove(myTable, 25))

 


20. 기본적인 입출력
 -. 파일 열기
    : myFile = io.open("test_data.lua", "w")     -- "a"

 -. 파일 닫기
    : io.close(myFile)

 -. 파일에 쓰기
    : myFile:write("-- Test lua file")

 -. 파일로 부터 읽기
    : res = myFile:read("*all")     --!< "*line", "*number"

 



[출처] Lua - 07. 표준 라이브러리|작성자 악마

 

◇ The first step is always the hardest ◇ : 네이버 블로그

인생은 한방 !

blog.naver.com



 

'[ Programing ] > Lua Scirpt' 카테고리의 다른 글

Lua - C++ 연동 간단한 예제  (0) 2022.03.06
Lua - C++과의 연동  (0) 2022.03.06
Lua - 명령문(Statements)  (0) 2022.03.06
Lua - 연산자(Expressions)  (0) 2022.03.06
Lua - 변수(Variables)  (0) 2022.03.05
Posted by Mister_Q