사용자 도구

사이트 도구


kb:luabinaryextension

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:luabinaryextension [2014/11/06 16:43] (현재)
줄 1: 줄 1:
 +====== Lua Binary Extension ======
 +윈도우즈 환경 하에서 DLL 파일을 이용해, 루아 확장 모듈을 만드는 방법이다.
 +
 +
 +====== 익스포트할 함수 만들기 ======
 +일단 익스포트할 함수들을 만들어야 한다. 여기에서는 DirectoryTraversing을 위한 _findfirst, _findnext, _findclose 함수를 익스포트하기로 한다. (클로져를 사용하면 좀 더 깔끔하게 빠질 것 같지만, 일단은 패스.)
 +<code cpp>
 +static int windows_find_first(lua_State* L)
 +{
 +    intptr_t ptr = -1;
 +    struct _finddata_t fileinfo = {0, };
 +
 +    if ((ptr = _findfirst(luaL_checkstring(L,​ 1), &​fileinfo)) == -1)
 +    {
 +        lua_pushnil(L);​
 +        return 1;
 +    }
 +
 +    lua_pushnumber(L,​ ptr);
 +    lua_pushstring(L,​ fileinfo.name);​
 +    lua_pushboolean(L,​ (fileinfo.attrib & _A_SUBDIR) ? 1 : 0);
 +
 +    return 3;
 +}
 +
 +static int windows_find_next(lua_State* L)
 +{
 +    intptr_t ptr = -1;
 +    struct _finddata_t fileinfo;
 +
 +    ptr = (intptr_t)luaL_checknumber(L,​ -1);
 +    if (_findnext(ptr,​ &​fileinfo) != 0)
 +    {
 +        lua_pushnil(L);​
 +        return 1;
 +    }
 +
 +    lua_pushstring(L,​ fileinfo.name);​
 +    lua_pushboolean(L,​ (fileinfo.attrib & _A_SUBDIR) ? 1 : 0);
 +
 +    return 2;
 +}
 +
 +static int windows_find_close(lua_State* L)
 +{
 +    _findclose((intptr_t)luaL_checknumber(L,​ -1));
 +    return 0;
 +}
 +</​code>​
 +
 +====== 패키지 등록 함수 만들기 ======
 +DLL을 이용하는 경우에도,​ 다른 패키지와 마찬가지로 패키지 등록 함수가 있어야 한다. 다만 루아 쪽에서 이 함수를 호출할 수 있어야 하므로, <​nowiki>​__declspec(dllexport)</​nowiki>​를 붙여줘야 한다.
 +<code cpp>
 +int __declspec(dllexport) luaopen_LuaExtension(lua_State* L)
 +{
 +    static const luaL_Reg windowslib[] = 
 +    {
 +        { "​find_first",​ windows_find_first },
 +        { "​find_next", ​ windows_find_next },
 +        { "​find_close",​ windows_find_close },
 +        { NULL,         NULL }
 +    };
 +
 +    luaL_register(L,​ "​win",​ windowslib);​
 +    return 0;
 +}
 +</​code>​
 +이 함수 이름은 약간 주의해야 하는데, luaopen_DLLNAME 형식으로 해줘야한다. 왜 그런지는 아래에서 설명한다. 위의 함수 4개를 빌드해서,​ LuaExtension.dll 파일을 만들었다고 하자. 이 파일을 패스로 등록된 어딘가에 복사한다.
 +
 +
 +====== 루아에서 DLL 불러오기 ======
 +2가지 방법이 있다.
 +
 +첫번째는 package.loadlib 함수를 명시적으로 사용하는 방법이다.
 +<code lua>
 +libinit = package.loadlib("​LuaExtension",​ "​luaopen_LuaExtension"​)
 +libinit()
 +</​code>​
 +loadlib 함수의 첫번째 인자는 DLL 이름이고,​ 두번째 인자는 패키지 등록 함수의 이름이다. DLL을 무사히 로드한 경우, 패키지 등록 함수를 리턴한다. 리턴값으로 받은 함수를 호출해주면 패키지를 등록할 수 있다.
 +
 +두번째는 그냥 require 구문을 이용하는 것이다.
 +<code lua>
 +require("​LuaExtension"​)
 +</​code>​
 +사실 require 구문 안에서 첫번째 방법과 똑같은 과정이 이루어진다. 다만 패키지 등록 함수는 모듈 이름을 이용해 추정하게 되는데, 그 형식이 위에서도 잠깐 나온 것처럼 luaopen_DLLNAME 형식이다. ​
 +
 +무사히 로드했다면,​ 이제 딱히 다른 패키지와 틀릴 것이 없다. 그냥 사용하면 된다. 아래의 예에서는 DLL 안의 DirectoryTraversing 함수를 이용해, 현재 디렉토리 안에 있는 모든 루아 파일들을 호출(require)하고 있다.
 +<code lua>
 +local ptr, name, is_dir = win.find_first("​.\\*.lua"​)
 +if ptr then
 +    repeat
 +        if not is_dir then
 +            require(string.sub(name,​ 1, -5))
 +        end
 +        name, is_dir = win.find_next(ptr)
 +    until name == nil
 +    win.find_close(ptr)
 +end
 +</​code>​
 +----
 +  * see also [[Lua]], [[LuaCppBinding]],​ [[LuaCSharpBinding]]
  
kb/luabinaryextension.txt · 마지막으로 수정됨: 2014/11/06 16:43 (바깥 편집)