본문 바로가기
프로그래밍

[Lua] C에서 루아 라이브러리를 사용하는법 - (2/2)

by dladbru 2018. 7. 31.

[Lua] C에서 루아 라이브러리를 사용하는법 - (2/2)

 

#include <windows.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifdef __cplusplus
}
#endif

#pragma comment(lib,"lua53.lib")

int lua_hack(lua_State* L)
{
	int count = 0;
	char str[256] = { 0x00, };

	strcpy_s(str, (char *)luaL_checkstring(L, 1));
	count = (int)luaL_checkinteger(L, 2);

	while (count-->0)
	{
		printf("Message: %s\n", str);
	}
	return 0;
}

int main(int argc, char **argv)
{
	lua_State *L;
	L = luaL_newstate();
	if ((INT)L == 0 || (INT)L == -1)
		return 0;

	luaL_openlibs(L);
	lua_register(L, "hack", lua_hack);
	lua_register(L, "hack2", lua_hack);
	if (luaL_dofile(L, "C:\\Users\\Kang\\Documents\\Visual Studio 2015\\Projects\\LuaT\\code.txt"))
	{
		printf("Failed...");
	}

	lua_close(L);
	return 0;
}

<Figure 0. 루아 스크립트 기본 사용 예제>

 

 

C++에서 만든 함수를 루아 스크립트에서 사용하는 예제로 hack이란 함수를 이용해 접근 가능하다.

 

스크립트에서 인자로 아래와 같은 형태로 이용가능하다.  luaL_checkstring은 명시적으로 문자열로 캐스팅해주자.

 

(char *)luaL_checkstring(L, 1); 
luaL_checkinteger(L, 2);

 

 

<Figure 1. hack 함수 사용 루아 스크립트>

 

 

hack이란 함수는 이렇게 사용하면된다.  KOREA가 5번 출력된다면 우리가 의도한 동작이 맞다.

<Figure 2. 5번 출력된 문자열>

 

우리가 의도했던대로 5번이 출력되었다. 만약 다른 시스템에서 10번을 출력되기를 원한다면 소스코드에서 10번을 출력시키는 코드로 변경해 컴파일해야하겠지만, 루아 스크립트와 함께라면 5를 10으로만 변경하면 된다.

 

int lua_hack2(lua_State* L)
{
	lua_pushstring(L, "Lua ZZang");

	return 1;
}


int lua_hack(lua_State* L)
{
	int count = 0;
	char str[256] = { 0x00, };

	strcpy_s(str, (char *)luaL_checkstring(L, 1));
	count = (int)luaL_checkinteger(L, 2);

	while (count-->0)
	{
		printf("Message: %s\n", str);
	}

	return 0;
}


int main(int argc, char **argv)
{
	lua_State *L;

	L = luaL_newstate();

	if ((INT)L == 0 || (INT)L == -1)
		return 0;

	luaL_openlibs(L);

	lua_register(L, "hack", lua_hack);
	lua_register(L, "hack2", lua_hack2);

	if (luaL_dofile(L, "C:\\Users\\Kang\\Documents\\Visual Studio 2015\\Projects\\LuaT\\code.txt"))
	{
		printf("Failed...");
	}

	lua_close(L);

	return 0;
}

<Figure 3. hack2 함수 추가>

 

 

hack2에서는 lua_pushstring 함수를 사용했는데 루아 스크립트에서 함수를 호출했을때 문자열을 리턴해줄 수 있다. 

lua_hack과 다르게 lua_hack2에서는 "return 1;" 을 해주는데 여기서 지정된 숫자는 리턴값의 갯수다.

 

pushstring말고도 lua_pushinteger 을 이용해 정수형을 리턴해주는 방법도 있으니 사용해보시길!

 

 

<Figure 4. hack2 함수 사용 스크립트>

 

hack2 함수는 "Lua ZZang" 문자열을 리턴해주고 hack을 통해 data 변수를 7번 출력할테니 보지 않아도 결과가 예상은 간다 .

 

<Figure 5. Lua ZZang 출력>

 

역시나 생각과 다르지 않은 결과와 함께 Lua의 기본적인 형태는 거의 대부분 써본듯 하다.  아직도 이해가 안간다면... 다른 루아 스크립트를 많이 찾아보기를 권한다. 

 

 

<Figure 6. lua 문자열 자르기>

 

이 글에서는 설명하지 않지만 lua에서 spliit같은 함수를 구현해서 사용할 수 있다. 예를들어 string.find 는 기본적으로 존재하므로 문자열 제어가 편리하다.

 

<Figure 7. dofile 기본 함수>

 

dofile 함수를 이용해 위에서 본 split를 쓸 수 있다. 주의해야 할 점으로는 배열의 시작이 1부터라는 점이다. C나 Python을 배운 사람은 0부터 시작하는 실수를 범하는 경우가 많다.

 

<Figure 8.  Figure 7 스크립트 사용 결과>

 

공백을 기준으로 나뉘어진것을 확인할 수 있다. 문자열 제어는 많은곳에서 사용되므로 알아두면 유용하다.

 

 

 

int main(int argc, char **argv)
{
	lua_State *L;
	L = luaL_newstate();
	if ((INT)L == 0 || (INT)L == -1)
		return 0;

	luaL_openlibs(L);
	lua_register(L, "hack", lua_hack);
	lua_register(L, "hack2", lua_hack2);

	if (luaL_dofile(L, "C:\\Users\\Kang\\Documents\\Visual Studio 2015\\Projects\\LuaT\\code.txt"))
	{
		printf("Failed...");
	}

	lua_State* L2=lua_newthread(L);

	lua_getglobal(L2, "SystemMessageCallBack");
	if (lua_isfunction(L2, -1)) 
	{
		lua_pushstring(L2, "Do you want a message?");
		lua_pcall(L2, 1, 0, 0);
	}
        lua_close(L2);        

	lua_close(L);
	return 0;
}

<Figure 9. cpp 에서 루아 스크립트 호출>

 

바뀐 부분은 L2의 선언부터 lua_pcall 호출 까지로 cpp에서 루아 스크립트를 호출 하는 코드이다.  L2를 생성하지 않고 L을 사용해도 되지만, 큰 스크립트를 작성할 경우 getglobal, lua_pushstring을 사용하다가 다른 부분에서 스택을 이용하다가 버그를 일으킬 수 있다.  설명이 어려울 순 있지만 쓰레드에 대한 개념이 있다면 이해할 것이라 생각한다.

 

lua_pcall 을 통해 SystemMessageCallback을 실행하게 되는데 2,3,4번째 인자에 대한 설명은 아래와 같다.

 

nagrs   : 루아 스크립트 함수에 전달될 인자 수           
                  이 인자수 만큼 스택에 전달된 매개변수 값들이 있어야 한다.
nresult : 루아 스크립트 함수가 수행된 이후에 돌려진 반환 값 수


errfunc : 루아 스크립트 함수내부에서 수행에 실패 했을때 
                 호출될 루아 함수가 저장된 스택을 지정해준다. 

                  모르겠으면 위와 같이 0을 지정해주면된다.


<Figure 10. SystemMessageCallback 구현>

 

 

SystemMessageCallback 을 정의하지 않으면 C의 lua_isfunction 리턴 값이 0이 된다. 그러므로 정의해주자.  나는 내가 정의한 문자열 이후에 붙여서 출력하는 코드를 작성했다. 

 

여기서 문자열을 ".." 을 통해 간편히 붙이는 방법도 있음을 확인하고 가시면 된다 ㅎㅎ...

 

 

 

<Figure 11. SystemMessageCallback을 사용한 모습>
이렇게 루아 스크립트의 기본적인 기능들을 적어놓았지만, 결국엔 사용하는 사람마다 다른 형태로 도움이 될것이라 생각한다.

 

 

 

이 글을 읽어주셔서 감사합니다.

 

 

 

반응형

댓글