devcat-studio / lich

lich: Lua-C++ Interoperation Helper

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

lich : Lua-C++ Interoperation Helper

소개

루아 C API를 직접 사용해서 바인딩 코드를 짜면 실수하기 쉽고 읽기 어렵습니다. lich를 쓰면 C++에서 루아 함수를 호출하거나, 컨테이너를 루아와 주고받거나, 루아 값에 대한 참조를 유지하는 등의 일을 간편하고 안전하게 할 수 있게 됩니다.

lich는 루아 5.1 에 대해 컴파일하고 테스트했습니다. 5.2나 5.3은 안해봤습니다.

사용 방법

준비

  • https://www.lua.org/ftp/lua-5.1.5.tar.gz 를 받아서 src 디렉토리 안의 내용을 lich 리파지터리의 lua-5.1.5 폴더 안에 복사해주세요.
  • lich/all.h를 인클루드하세요.
  • luaL_newstate() 호출 직후에 lich::enable_ref(L) 을 불러주세요.

load_program

lich::ref fn;
pair<bool, string> result = lich::load_program(L, "return 42", "", fn);
  • 루아 프로그램을 컴파일하여 루아 함수로 바꾼 뒤, 실행하지 않고 참조를 갖고 있으려면 load_program을 사용하세요.
  • 컴파일이 성공하면 result.firsttrue가 담기고, 루아 함수가 fn에 담깁니다.
  • 컴파일이 실패하면 result.firstfalse가, result.second에는 에러 메시지가 담깁니다.

run_program

tuple<int> rv;
pair<bool, string> result = lich::run_program(L, "return 42", "", rv);
assert(get<0>(rv) == 42);
  • 루아 프로그램을 컴파일하여 루아 함수로 바꾼 뒤, 바로 실행하려면 run_program을 사용하세요.
  • 컴파일과 실행이 성공하면 result.firsttrue가 담기고, 실행 결과가 마지막 인자에 담깁니다.
  • 컴파일이 실패하거나 실행 중 에러가 발생하면 result.firstfalse가, result.second에는 에러 메시지가 담깁니다.
  • 리턴값이 여럿이어도 받아올 수 있습니다. tuple<int, int, string> 과 같이 하면 됩니다.
  • 특정 C++ 타입을 가정하지 않고 루아 값 형태를 유지한 채로 참조만 가져올 수도 있습니다. int 대신 lich::ref를 사용해 보세요.

pcall(ref, ARG, RET)

lich::ref ref;
lich::load_program(L, "return 42", "", ref);

tuple<int> rv;
lich::pcall(ref, tuple<>(), rv);
assert(get<0>(rv) == 42);
  • 루아 함수를 실행하려면 pcall을 사용하세요.
  • 리턴값의 의미는 run_program과 같습니다.
  • 인자와 리턴값 모두 tuple로 주고받습니다.

pcall(L, 전역 함수 이름, ARG, RET)

// type(1)
tuple<string> rv;
lich::pcall(L, "type", tuple<int>(1), rv);
assert(get<0>(rv) == "number");

pcall(L, (모듈과 함수 이름), ARG, RET)

// string.rep('아', 5)
tuple<string> rv;
lich::pcall(L, make_tuple("string", "rep"), make_tuple("아", 5), rv);
assert(get<0>(rv), "아아아아아");

pcall(L, (객체와 메서드 이름), ARG, RET)

// s = "justive rains from above"
lich::push(L, "justive rains from above");
lich::ref s;
lich::to(L, -1, s);
lua_pop(L, 1);

// s:upper() == s.upper(s)
tuple<string> rv;
lich::pcall(L, tie(s, "upper"), tie(s), rv);
assert(get<0>(rv), "JUSTIVE RAINS FROM ABOVE");

C++ 값으로 변환

  • 원하는 C++ 타입에 대해 pushto 전역 함수를 오버로드하면 run_program, pcall, ref::to 에서 그 타입의 값을 바로 사용하게 할 수 있습니다. 현재는 몇몇 기본 타입과 std::string, std::vector, std::map에 대해서만 구현해 두었습니다.

ref

  • 루아 값에 대한 참조를 C++에서 유지하고 싶으면 ref를 사용하세요.
  • ref 객체로부터 특정 C++ 타입으로 변환하고 싶으면 ref::to 를 사용하면 됩니다.
  • 반드시 lua_close를 하기 전에 모든 ref 객체를 소멸시켜야 합니다! 그러지 않으면 ref 객체의 소멸자가 불리는 시점에 크래시가 납니다. 주의하세요.

빌드/테스트 방법

Visual Studio

  • Visual Studio 2015에서 빌드하고 테스트했습니다.
  • vs2015/lich-test.sln 을 열고 실행해 보세요.
  • 콘솔에 OK가 뜨면 정상입니다.

g++

  • g++ 4.8.2에서 빌드하고 테스트했습니다.
  • gcc 폴더에서 build_and_test 쉘 스크립트를 실행하세요(cmake가 필요합니다).
  • 콘솔에 OK가 뜨면 정상입니다.

남은 일

  • C++ 객체를 shared_ptr을 통해 루아에 노출하기

About

lich: Lua-C++ Interoperation Helper

License:MIT License


Languages

Language:C++ 92.5%Language:C 3.5%Language:Batchfile 3.2%Language:CMake 0.8%Language:Shell 0.1%