본문 바로가기

3.구현/Lua

Lua extention (루아 확장 모듈) 만들기

여기서는 루아의 embedded보다는 extension을 살펴보기로 하겠습니다. 실제를 루아의 embedded를 더 많이 사용하고 있기 때문에 extension 활용이 떨어졌습니다. 그러다가 최근에 루아를 사용해서 테스트 스크립트를 작성하다가 extension에 대한 필요가 생겼습니다. 만들어놓은 이유가 다 있네요.
여기서는 간단한 예제를 통해서 extension을 사용하는 법을 아주 간략하게 살펴볼 것입니다.

작성자: http://ospace.tistory.com/,2015.02.24 (ospace114@empal.com)

기본사항

먼저, 루아 extension이란 루아를 확장하기 위한 기능입니다. Embedded가 아닌 단순히 스크립트를 슬행해서 동작하는 경우 필요한 기존에 없던 기능을 구현하려고 합니다. 기존에 없던 기능이기 때문에 이를 하려면 당연히 루아 외부 모듈이 필요합니다. 이러한 외부모듈은 대부분의 스크립트 언어에서는 동적 라이브러리 형태로 존재합니다. 이것은 당연히 정적 라이브러리로 존재하면 링크라는 과정을 거쳐야 사용할 수 있기 때문이며 실행 중에 정적 라이브러리를 사용할 수 없기 때문입니다.
그렇기 때문에 루아에서 extension 모듈은 동적 라이브러리로 동작합니다. 그렇기 때문에 동적 라이브러리를 만들어야 합니다. 물론 아무렇게나 만드는 것이 아니라 특정한 함수 형식을 갖는 동적 라이브러리를 만들면 됩니다.
만약에 C++을 기반으로 동적 라이브러리를 작성을 하게 된다면, 주의할 것이 있습니다. 외부에서 호출할 함수명 앞에는 extern "C"를 포함해야 합니다. 이건 기초라서 뭐 자세히는 말하지 않겠지만, 루아가 C 기반이고 일반적으로 동적라이브러리는 C 함수 호출형식이 기본이기 때문입니다.

C++에서는 동적 라이브러러에서 호출할 함수는 extern "C"를 앞에 붙여야 합니다.

Windows에서는 동적 라이브러리가 좀 독특합니다. ㅡ.ㅡ;;; 이는 동적라이브러리를 만들기 위해서는 몇개 작업들이 필요합니다. DllMain 함수를 정의해서 여러 이벤트에 따라 처리하는 로직을 정의할 수 있습니다. 특히 외부에서 호출할 함수명 앞에 __declspec(dllexport)를 선언해줘야 호출이 가능합니다. DllMain 함수는 잊어버려도 이 것은 잊어버리면 안됩니다. 그렇지 않다면 소중한 당신의 시간이 쓸데없이 소비하게 될 것입니다.

즉, Windows에서는 호출할 함수 앞에 __declspec(dllexport)를 붙여야 합니다.

각 컴파일러 별로 동적 라이브러리 만들때 내용은 구글링을 해보기 바랍니다. 다른 분들이 더 잘 설명해줄 것입니다.

extern "C" __declspec(dllexport) int foo() {}

확장모듈 만들기

Deployment extension

루아에서 확장 모듈을 만들기 위한 몇가지 제약사항이 있습니다.
당연히 루아에서 로딩할 확장 모듈 이름과 파일 이름은 동일해야합니다.
루아에서 확정 모듈 로딩할 때 기본적으로 호출하는 함수 명은 luaopen_<파일명> 함수 형태로 작성해야 합니다.
당연히 확장 모듈은 루아가 인식할 수 있는 경로에 있어면 됩니다. 잘 모르면, 루아 실행 파일이 있는 디렉토리에 넣으면 됩니다.
예를 들어 Windows에서 foo라는 확장 모듈을 만든다면,

  • 확장모듈 파일명: foo.dll
  • 기본 호출 함수명: luaopen_foo

Foo extension

아래는 foo라는 예제 코드입니다.

#include <stdio.h>
#include <time.h>
#include <lua.hpp>
#include <Windows.h>

static int lua_now(lua_State *L) {
  time_t now;
  time(&now);

  char buf[128];
  ctime_s(buf, sizeof(buf), &now);
  printf("%s", buf);
  return 0;
}

static int lua_msgbox(lua_State *L) {
  const char *msg = luaL_checkstring(L,1);
  int ret = MessageBox(NULL, msg, "Information", MB_OK|MB_ICONINFORMATION);
  lua_pushnumber(L, ret);
  return 1;
}

extern "C" __declspec(dllexport) int luaopen_foo(lua_State *L) {
  lua_register(L, "now", lua_now);
  lua_register(L, "msgbox", lua_msgbox);
  return 1;
}

lua_now 함수는 현재 시간을 출력해주는 함수이고, lua_msgbox 함수는 메시지 박스를 화면에 표시하는 함수입니다.
이를 루아에서 사용하는 방법은 다음과 같습니다.

require "foo"
now()
msgbox("hello")

작동 순서를 살펴보겠습니다. 루아 함수 require()에서 동적 라이브러리를 로딩을 합니다. 그리고 함수에서 luaopen_foo 함수를 찾아서 실행합니. 그러면 자동으로 now 함수와 msgbox 함수가 루아에 등록이 됩니다. 이후로는 등록된 함수를 사용할 수 있습니다.

결론

루아에서 확장 모듈을 만드는 방법을 간단히 살펴보았습니다. 이를 활용하면 워하는 기능을 루아 모듈을 통해서 쉽게 확장이 될 것입니다. 물론 위의 내용은 모듈를 로딩하는 것만 살펴보았지만, 모듈을 해제하는 부분도 필요할 것입니다. 이 부분은 추후 시간이 되면 더 다룰려고 합니다.

모드 즐프하기를.... ospace.

참조

[1] Lua site, http://www.lua.org/

[2] Building Modules, 2015.02.24, http://lua-users.org/wiki/BuildingModules

반응형

'3.구현 > Lua' 카테고리의 다른 글

Lua에서 객체지향적 코딩 하기  (0) 2012.02.15
lua 동향(2011/10)  (0) 2011.10.26
6. Lua의 C 바인딩  (0) 2009.01.28
5. Lua 메타테이블(metatable)  (0) 2008.02.28
Lua 5.x와 Lua 4.0 호환성  (0) 2008.01.21