[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을 사용한 모습>
이렇게 루아 스크립트의 기본적인 기능들을 적어놓았지만, 결국엔 사용하는 사람마다 다른 형태로 도움이 될것이라 생각한다.
이 글을 읽어주셔서 감사합니다.
'프로그래밍' 카테고리의 다른 글
아이폰 앱 코드 패치 트윅 개발 with theos (0) | 2019.06.03 |
---|---|
[WINE] 맥 OS에서 python 스크립트를 EXE로 빌드하기 (2) | 2019.05.15 |
[Lua] C에서 루아 라이브러리를 사용하는법 - (1/2) (0) | 2018.07.26 |
[Python] 프록시 서버 - http,https 통신 예제 (0) | 2018.07.26 |
[Zydis] 디스어셈블러 라이브러리 (0) | 2018.07.24 |
댓글