kgc2006 template metaprogramming을 이용한 luatinker 구현

96
Template metaprogramming 을 통한 LuaTinker 의 구 이권일 Nexon

Upload: sang-goo-kwon

Post on 07-Jul-2015

504 views

Category:

Technology


5 download

DESCRIPTION

2006년 KGC에서 Nexon의 이권일님께서 발표하신 LuaTinker 구현에 대한 PPT 입니다. 인터넷에 찾아보니까 공유된 내용이 없어서 제가 저장해 두었던 것을 공유합니다. 혹시나 문제가 된다면 삭제하겠습니다.

TRANSCRIPT

Page 1: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template metaprogramming 을 통한 LuaTinker 의 구현

이권일Nexon

Page 2: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

발표 대상

현재 LuaTinker 를 사용하고 있는 사람 C++ Template 을 사용한 Metaprogramming

을 배우고자 하는 사람 STL 이외의 Template 을 유용하게 사용할 방

법을 찾고 있는 사람

Page 3: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua 에 대한 소개

Lua 는 가볍고 유연한 스크립트 언어 브라질 Computer Graphics Technology

Group 소속 3 명의 멤버가 시작 현재 5.1 까지 발표되어 있고 Python 과 함께

많은 게임들에서 사용되고 있음 reflective, imperative and procedural

language C 언어와 매우 비슷한 문법을 갖고 있다 .

Page 4: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template Metaprogramming

metaprogramming = 코드를 만드는 코드로C++ Template 을 이용하여 만들어진다 .

최근 Boost Metaprogramming Libary 를 사용하는 개발자들이 늘어나고 있다 .

C++ Template Metaprogramming 서적 추천

Page 5: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

LuaTinker 의 소개

Lua 와 C++ 간의 원활한 통신을 하기 위해 제작된 Open Source 라이브러리

기존에 사용하던 LuaBind 를 사용하던 상태에 바로 적용 가능

template metaprogramming 으로 구현됨 빠른 컴파일 시간 !!

Page 6: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua 스크립트와 와 C 함수

Lua 와 C 언어간 통신 방법중 하나로 Lua 스크립트에서 미리 등록된 C 언어의 함수를 호출할 수 있다 .

Lua 는 아래 한가지 함수형만 등록이 가능하고 함수 호출에 사용된 인자들은 Lua API 와 lua_State 핸들을 통해 접근하게 된다 .

typedef int (*lua_CFunction) (lua_State *L);

Page 7: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua C 함수의 구현 (1)/* 다음은 left + right 값을 리턴해주는 간단한 C 함수이다 . */ int addition(int left, int right){

return left + right;}

/* addition 을 Lua C 함수로 등록한다 . */int addition_lua(lua_State *L){

/* Lua Stack 에서 left, right 값을 읽어온다 */ int left = lua_tonumber(L, 1);int right = lua_tonumber(L, 2);/* addtion() 을 실행한다 . */ int result = addition(left, right);/* Lua Stack 에 left + right 값을 넣고 1 을 리턴한다 */ lua_pushnumber(L, result);return 1;

}

Page 8: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua C 함수의 등록 (1)/* lua 에서 호출할 함수 이름을 Stack 에 넣는다 . */ lua_pushstring(L, "addition");/* Lua C 함수 포인터를 Stack 에 넣는다 . */ Lua_pushcclosure(L, addition_lua, 0);/* 전역으로 addit ion 함수를 등록한다 . */ lua_settable(L, LUA_GLOBALSINDEX);

-- Lua 에서 실행예

result = addition(10, 20)

print(result)

>30

Page 9: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua C 함수의 문제점

Lua 에서 호출되기를 원하는 모든 함수를 만들어 주어야 한다 .

Stack 에 접근하기 위해서 일일이 Lua Stack 접근 함수를 사용해야한다 .

Lua 와 호환되지 않는 자료형은 사용할 수 없기 때문에 추가적인 코드를 작성하지 않고 class 나 struct 를 사용할 수 없다 .

Page 10: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Upvalue 의 활용

Upvalue 는 Lua 에서 C 함수를 등록할때 Lua C 함수 이외에 별도의 정보를 저장할 수 있는 영역이다 .

Upvalue 에는 Lua 자료형을 넣을 수 있는데 void* 형이 존재하며로 함수 포인터를 넣어서 Lua C 코드 작성량을 줄일 수 있다 .

Page 11: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua C 함수의 구현 (2)int addition(int left, int right) { return left + right; }Int subtract(int left, int right) { return left - right; }

/* Upvalue 를 이용하는 을 Lua C 함수로 등록한다 . */int arithmetic_lua(lua_State *L){

/* Lua Stack 에서 left, right 값을 읽어온다 */ int left = lua_tonumber(L, 1);int right = lua_tonumber(L, 2);/* Upvalue 에서 함수 포인터를 얻어온다 . */ void* func = lua_touserdata(L, lua_upvalueindex(1));/* C 함수 포인터를 실행한다 . */ int result = ((int(*)(int,int))func)(left, right);/* Lua Stack 에 계산 결과값을 넣고 1 을 리턴한다 */ lua_pushnumber(L, result);return 1;

}

Page 12: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua C 함수의 등록 (2)/* lua 에서 호출할 함수 이름을 Stack 에 넣는다 . */ lua_pushstring(L, "addition");/* addition 함수 포인터를 Upvalue 로 추가한다 . */ lua_pushlightuserdata(L, (void*)&addition);/* int(*)(int, int) 함수를 호출하는 Lua C 함수를 넣는다 . */ Lua_pushcclosure(L, arithmetic_lua, 1);/* 전역으로 addit ion 함수를 등록한다 . */ lua_settable(L, LUA_GLOBALSINDEX);

/* lua 에서 호출할 함수 이름을 Stack 에 넣는다 . */ lua_pushstring(L, “subtract");/* subtract 함수 포인터를 Upvalue 로 추가한다 . */ lua_pushlightuserdata(L, (void*)&subtract);/* int(*)(int, int) 함수를 호출하는 Lua C 함수를 넣는다 . */ Lua_pushcclosure(L, arithmetic_lua, 1);/* 전역으로 subtract 함수를 등록한다 . */ lua_settable(L, LUA_GLOBALSINDEX);

Page 13: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Upvalue 를 사용한 Lua 실행-- Upvalue 를 활용한 Lua 실행예result = addition(10, 20)print(result)>30

result = subtract(10, 20)print(result)>-10

Page 14: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Upvalue 활용의 한계

다른 인자값을 갖는 경우 모든 형태의 함수를 만들어 줘야 한다 .

함수 포인터를 쓰기 때문에 등록된 함수와 호출해주는 Lua C 함수가 정확히 같은 자료형 및 함수 포인터호출을 해줘야 한다 .

Page 15: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

LuaTinker 가 제시하는 해결책

Lua C 함수 등록을 간편하게 해주고 중간 호출 코드를 자동으로 생성해 준다 .

Stack 에 접근하는 함수를 제공하여 자료형에 따른 적절한 변환을 지원한다 .

class/struct 의 멤버 함수 및 멤버 변수 Stack 에 접근하는 함수를 제공하여 자료형에 따른 적절한 변환을 지원한다 .

Page 16: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

LuaTinker 와 Lua C 함수 등록

lua_tinker::def() 함수에 함수 명과 함수 포인터를 넘겨준다 .

내부에서 자동적으로 template 를 통해 functor 함수를 생성해주고 stack 접근코드까지 생성해준다 .

/* int addition(int, int), subtract( int, int) 함수 등록 예 */ lua_tinker::def(L, “addition”, addtion);lua_tinker::def(L, “subtract”, subtract);

Page 17: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::def() 코드/* F 자료형은 함수 포인터형이다 . */template<typename F> void def(lua_State* L, const char* name, F func){

/* 함수명을 Stack 에 넣기 */lua_pushstring(L, name);/* Upvalue 에 함수 입력 */lua_pushlightuserdata(L, func); /* template 함수로 F 자료형을 분석 후 functor 등록 함수 */push_functor(L, func);/* Lua 전역으로 함수 등록 */ lua_settable(L, LUA_GLOBALSINDEX);

}

Page 18: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::push_functor()

lua_tinker::def() 에서 typename F 로 선언된 함수 변수형을 typename RVal, T1, T2… T6 등이 조합된 함수형으로 분리

C++ 에서 함수 인자로 void 선언이 불가능하기 때문에 각각 함수 인자 종류에 맞춰 overloading 을 구현

분리된 RVal, typename T1, T2… T6 들은 Stack 접근을 위해서 사용됨

Page 19: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

push_functor() 와 함수 뽀개기/* def(“addition”, addtion) 호출시 typename F = int (*)(int,int) 자료형이

된다 . */template<typename F>void def(lua_State* L, const char* name, F func){

…push_functor(L, func); …

}

/* push_fuctor 에 int (*)(int,int) 함수 포인터가 넘어오면 typename F 였던함수자료형이 분석되어 각 typename Rval=int, T1=int, T2=int 을 채워준다 */

template<typename RVal, typename T1, typename T2> void push_functor(lua_State *L, RVal (*func)(T1,T2)){

lua_pushcclosure(L, functor<T1,T2>::invoke<RVal>, 1);}

Page 20: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

push_functor() overloading typename F 를 분리하기 위해 함수 포인터형을 선언

하는데 void 사용 불가 C++ overloading 을 활용해서 함수가 0~5 개의 인자릴 받을때에 적용하여 push_functor 를 구현

int addition(int,int) -> RVal (*func)(T1,T2) RVal=int, T1=int, T2=int -> int (*func)(int,int) YES!!int increase(int) -> RVal (*func)(T1,T2) RVal=int, T1=int, T2=void -> int (*func)(int,void) NO!!int increase(int) -> RVal (*func)(T1) RVal=int, T1=int, T2=void -> int (*func)(int) YES!!

Page 21: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

push_functor() 선언template<typename RVal> void push_functor(lua_State *L, RVal (*func)());

template<typename RVal, typename T1> void push_functor(lua_State *L, RVal (*func)(T1));

template<typename RVal, typename T1, typename T2> void push_functor(lua_State *L, RVal (*func)(T1,T2));

template<typename RVal, typename T1, typename T2, typename T3> void push_functor(lua_State *L, RVal (*func)(T1,T2,T3));

template<typename RVal, typename T1, typename T2, typename T3, typename T4> void push_functor(lua_State *L, RVal (*func)(T1,T2,T3,T4));

template<typename RVal, typename T1, typename T2, typename T3, typename T4, typename T5>

void push_functor(lua_State *L, RVal (*func)(T1,T2,T3,T4,T5));

Page 22: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 객체

lua_tinker::functor 는 template 로 구성되어있고 Lua 에 등록 가능한 Lua C 함수 functor::ivoke() 를 갖고 있는 함수체이다 .

호출시 stack 에서 함수 인자를 적절한 형태로 읽어오고 Upvalue 에 들어있는 함수 포인터를 읽어와 실행한다 .

리턴값이 없는 경우의 예외 처리를 위해 template 에 대한 명시적 전문화를 사용한다 .

Page 23: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename T1, typename T2>struct functor<T1,T2> {

template<typename RVal>static int invoke(lua_State *L) {

push_<RVal> (L,upvalue_< RVal(*)(T1,T2) >(L)(

pop_<T1>(L,1), pop_<T2>(L,2))

); return 1;

}};

Page 24: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename T1, typename T2>struct functor<T1,T2> {

template<typename RVal>static int invoke(lua_State *L) {

push_<RVal> (L,upvalue_< RVal(*)(T1,T2) >(L)(

pop_<T1>(L,1), pop_<T2>(L,2))

); return 1;

}};

Page 25: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

push_<int> (L,upvalue_< int(*)(int,int) >(L)(

pop_<int>(L,1), pop_<int>(L,2))

); return 1;

}};

Page 26: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

push_<int> (L,upvalue_< int(*)(int,int) >(L)(

pop_<int>(L,1), pop_<int>(L,2))

); return 1;

}};

Page 27: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left;push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

pop_<int>(L,1), pop_<int>(L,2))

); return 1;

}};

Page 28: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = pop_<int>(L,1);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

pop_<int>(L,1), pop_<int>(L,2))

); return 1;

}};

Page 29: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = pop_<int>(L,1);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, pop_<int>(L,2))

); return 1;

}};

Page 30: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, pop_<int>(L,2))

); return 1;

}};

Page 31: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, pop_<int>(L,2))

); return 1;

}};

Page 32: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right;push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, pop_<int>(L,2))

); return 1;

}};

Page 33: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = pop_<int>(L,2);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, pop_<int>(L,2))

); return 1;

}};

Page 34: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = pop_<int>(L,2);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, right,)

); return 1;

}};

Page 35: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, right,)

); return 1;

}};

Page 36: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, right,)

); return 1;

}};

Page 37: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, right,)

); return 1;

}};

Page 38: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int) = upvalue_< int(*)(int,int) >(L);push_<int> (

L,upvalue_< int(*)(int,int) >(L)(

left, right,)

); return 1;

}};

Page 39: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int) = upvalue_< int(*)(int,int) >(L);push_<int> (

L,func(

left, right,)

); return 1;

}};

Page 40: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int) = upvalue_< int(*)(int,int) >(L);push_<int> (

L,func(left, right));

return 1; }

};

Page 41: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int) = lua_touserdata(L,lua_upvalueindex(1));push_<int> (

L,func(left, right));

return 1; }

};

Page 42: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int, int) = (int(func*)(int, int) )

lua_touserdata(L,lua_upvalu…);push_<int> (

L,func(left, right));

return 1; }

};

Page 43: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);push_<int> (

L,func(left, right));

return 1; }

};

Page 44: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);int result;push_<int> (

L,func(left, right));

return 1; }

};

Page 45: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);int result = func(left, right);push_<int> (

L,func(left, right));

return 1; }

};

Page 46: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);int result = func(left, right);push_<int> (

L,result);

return 1; }

};

Page 47: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);int result = func(left, right);push_<int> (L, result); return 1;

}};

Page 48: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::functor 풀이/* int addit ion(int left, int r ight) 를 넣는다고 했을때 */template<typename int, typename int>struct functor<int,int> {

template<typename int>static int invoke(lua_State *L) {

int left = lua_tonumber(L,1);int right = lua_tonumber(L,2);int(func*)(int,int) = (int(func*)(int,int) )lua_touserdata(L,lua_upvalu…);int result = func(left, right);lua_pushnumber(L, result); return 1;

}};

Page 49: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker 와 push_(), pop_()

lua_tinker::push_(), lua_tinker::pop_() 함수는 Lua Stack 에 접근하여 데이터를 교환하는 함수들이다 .

push_() 와 pop_() 모두 template 으로 제작되었으며 각 타잎에 따른 명시적 전문화으로 적합한 데이터 교환이 이뤄진다 .

명시적 전문화가 되지 않은 구조체 , 클래스의 경우 Lua 내의 metatable 을 붙여서 객체로 취급하고 특별한 처리를 한다 .

Page 50: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::push_() 코드/* template 으로 선언되고 1:1 변환이 가능한 것은 명시적 전문화가 되어

있다 . */ template<typename T> void push_(lua_State *L, T ret);

/* 명시적 전문화 : int 는 number 자료형으로 변환이 가능하다 . */ template<> void push_(lua_State *L, int ret) {

lua_pushnumber(L, ret);}/* 명시적 전문화 : const char* 는 string 자료형으로 변환이 가능하다 . */template<> void push_(lua_State *L, const char* ret) {

lua_pushstring(L, ret);}/* 변환 존재하지 않을 경우 userdata 로 변환하는 type2lua() 를 호출한

다 . */ template<typename T> void push_(lua_State *L, T ret) {

type2lua<T>(L, ret);}

Page 51: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

1:1 변환이 불가능한 자료형

Lua 와 1:1 변환이 불가능한 자료형은 Lua에서 할당받은 메모리에 복사해 넣는다 .

Value, Pointer, Reference 여부에 따라 userdata 에 전체를 복사하거나 포인터만 넣어주게 된다 .

enum 는 별개의 데이터 형이지만 Lua 내에서 값에 접근하기 좋게 숫자로 취급한다 .

변환에는 lua_tinker::type2lua() 함수를 호출하고 이 함수는 template if 문이 사용되었다 .

Page 52: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

type2lua() 코드template<typename T>void type2lua(lua_State *L, T val) {

if_<is_enum<T>::value /* T 자료형이 enum 인가 ? */ ,enum2lua<T> /* enum2lua functor */ ,object2lua<T> /* object2lua fuctor */ >::type::invoke(L, val); /* functor 를 호출한다 . */

}

template<typename T>struct enum2lua { static void invoke(lua_State *L, T val); }

template<typename T>struct object2lua { static void invoke(lua_State *L, T val); }

Page 53: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

template if 구문

3 개의 인자를 받는 template 구조체 첫번째 bool 조건에 따라 구조체 내의 type

자료형이 A 또는 B 형으로 정의됨 type 은 ‘자료형’ 이기 때문에 함수 포인터나

인스턴스가 못오고 functor 를 사용한다 .

template<bool C, typename A, typename B> struct if_ {};template<typename A, typename B> struct if_<true, A, B> { typedef A type; };template<typename A, typename B> struct if_<false, A, B> { typedef B type; };

if_<true, int, char>::type == intif_<false, int, char>::type == char

Page 54: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

type2lua<T>(L, ret);}

Page 55: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

type2lua<T>(L, ret);}

/* lua_tinker::type2lua() 함수 */template<typename T>void type2lua(lua_State *L, T val){

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

Page 56: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

type2lua<T>(L, ret);}

/* lua_tinker::type2lua() 함수 */template<typename T>void type2lua(lua_State *L, T val){

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

Page 57: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

type2lua<T>(L, ret);}

/* lua_tinker::type2lua() 함수 */template<typename T>void type2lua(lua_State *L, T val){

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type:: invoke(L, val);}

Page 58: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

i f_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type:: invoke(L, val);}

Page 59: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 60: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 61: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret=APPLE) {

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 62: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 63: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value,enum2lua<FRUIT>,object2lua<FRUIT>

>::type:: invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 64: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type:: invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };

Page 65: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<bool C, typename A, typename B> struct if_ {};template<typename A, typename B> struct if_<true, A, B> { typedef A type; };template<typename A, typename B> struct if_<false, A, B> { typedef B type; };

Page 66: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<bool C, typename A, typename B> struct if_ {};template<typename A, typename B> struct i f_< true, A, B> { typedef A

type; };template<typename A, typename B> struct if_<false, A, B> { typedef B type; };

Page 67: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A, typename B> struct i f_< true, A, B> { typedef A

type; };

Page 68: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A, typename B>struct i f_<true, A, B>{

typedef A type; };

Page 69: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A=enum2lua<FRUIT>, typename

B=object2lua<FRUIT>>struct if_<true, A, B>{

typedef A type; };

Page 70: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A=enum2lua<FRUIT>, typename

B=object2lua<FRUIT>>struct if_<true, enum2lua<FRUIT>, B>{

typedef A type; };

Page 71: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A=enum2lua<FRUIT>, typename

B=object2lua<FRUIT>>struct if_<true, enum2lua<FRUIT>, B>{

typedef enum2lua<FRUIT> type; };

Page 72: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<typename A=enum2lua<FRUIT>, typename

B=object2lua<FRUIT>>struct if_<true, enum2lua<FRUIT>, object2lua<FRUIT>>{

typedef enum2lua<FRUIT> type; };

Page 73: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<>struct if_<true, enum2lua<FRUIT>, object2lua<FRUIT>>{

typedef enum2lua<FRUIT> type; };

Page 74: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

if_<is_enum<FRUIT>::value = true,enum2lua<FRUIT>,object2lua<FRUIT>

>::type::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<>struct if_<true, enum2lua<FRUIT>, object2lua<FRUIT>>{

typedef enum2lua<FRUIT> type; };

Page 75: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<FRUIT> void push_(lua_State *L, FRUIT ret=APPLE) {

enum2lua<FRUIT>::invoke(L, val);}

/* 테스트 enum 데이터 */enum FRUIT { APPLE, BANANA, GRAPE };/* template if 코드 */ template<>struct if_<true, enum2lua<FRUIT>, object2lua<FRUIT>>{

typedef enum2lua<FRUIT> type; };

Page 76: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }

Page 77: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename T> void push_(lua_State *L, T ret) {

if_<is_enum<T>::value,enum2lua<T>,object2lua<T>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;

Page 78: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;

Page 79: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;

Page 80: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<bool C, typename A, typename B> struct if_ {};template<typename A, typename B> struct if_<true, A, B> { typedef A type; };template<typename A, typename B> struct if_<false, A, B> { typedef B type; };

Page 81: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<bool C, typename A, typename B> struct if_ {};template<typename A, typename B> struct if_<true, A, B> { typedef A type; };template<typename A, typename B> struct i f_<false, A, B> { typedef B

type; };

Page 82: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<typename A, typename B>struct i f_<false, A, B> {

typedef B type; };

Page 83: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<enum2lua<Damage>, object2lua<Damage>>struct if_<false, A, B> {

typedef B type; };

Page 84: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<enum2lua<Damage>, object2lua<Damage>>struct if_<false, enum2lua<Damage>, object2lua<Damage>> {

typedef object2lua<Damage> type; };

Page 85: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<enum2lua<Damage>, object2lua<Damage>>struct if_<false, enum2lua<Damage>, object2lua<Damage>> {

typedef object2lua<Damage> type; };

Page 86: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

if_<is_enum<Damage>::value = false,enum2lua<Damage>,object2lua<Damage>

>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<enum2lua<Damage>, object2lua<Damage>>struct if_<false, enum2lua<Damage>, object2lua<Damage>> {

typedef object2lua<Damage> type; };

Page 87: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Template if 구문 풀이/* lua_tinker::push() 함수의 기본형 */ template<typename Damage> void push_(lua_State *L, T ret=myDamage) {

object2lua<Damage>::type::invoke(L, val);}

/* 테스트 struct 데이터 */Struct Damage { int value; int count; }Damage myDamage;/* template if 코드 */ template<enum2lua<Damage>, object2lua<Damage>>struct if_<false, enum2lua<Damage>, object2lua<Damage>> {

typedef object2lua<Damage> type; };

Page 88: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

enum2lua {} functor enum 값을 Lua 의 number 타잎으로 변환하

여 Stack 에 넣어준다 . Template if 문에 사용되기 위해서 함수체로

만들어졌고 is_enum<T> 평가자와 함께 쓰이게 된다 .template<typename T>struct enum2lua {

static void invoke(lua_State *L, T val) {/* number 타잎으로 값을 Lua Stack 에 밀어넣는다 . */ lua_pushnumber(L, (int)val);

}};

Page 89: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

object2lua {} functor

template if 문에 사용될 수 있게 만들어진 functor 로 invoke() 함수를 갖고 있다 .

어떠한 object 를 인자로 받아 Lua 로부터 할당받은 메모리에 복사하는 역할을 한다 .

넘어온 object 가 value, pointer, reference 에 따라서 객체 전체 복사 , 포인터 복사 , 리퍼렌스 복사중 한가지 작업을 하게된다 .

Page 90: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker::object2lua 코드template<typename T>struct object2lua { /* template if 에 사용하게 만들어진 functor */

static void invoke(lua_State *L, T val) {

/* 다중 if 문이 사용되어 포인터 , 리퍼렌스 , 값 여부를 체크한다 . */

if_<is_ptr<T>::value,ptr2lua<base_type<T>::type> /* 기본 자료형을 찾는다 */ ,if_<is_ref<T>::value

,ref2lua<base_type<T>::type>,val2lua<base_type<T>::type>

>::type>::type::invoke(L, val);

/* 생성된 개체의 metatable 을 설정한다 . */ class_<class_type<T>::type>::push_meta(L);lua_setmetatable(L, -2);

} };

Page 91: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

Lua 에서의 객체

lua_tinker 는 struct/class 는 멤버 함수 , 멤버 변수의 접근이 가능을 제공해야한다 .

Lua 는 객체지향 언어가 아니지만 table 이란 자료형을 통해서 구조체와 흡사한 기능을 제공하고 있다 .

Lua 에서 제공하는 metatable 이란 것을 통해서 table 접근용 operator 들을 재정의해서 struct/class 에 대한 지원을 구현하고 있다 .

Page 92: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

lua_tinker 와 메타테이블

Lua 메타테이블은 어떠한 값이나 가질 수 있고 메타테이블을 통해 기본적으로 정해진 속성들을 변경할 수 있다 .

lua_tinker 는 메타테이블의 여러 기능중 테이블 접근에 사용하는 . 오퍼레이터와 Garbage Collecting 함수를 오버라이드 한다 .

Page 93: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

메타테이블 __index __index 를 재정의하면 table 에서 어떠한 값

을 읽어오는 함수를 재정의한다 . -- Lua 에서는 [] 와 . 오퍼레이터가 동일하게 작동한다 .value = character[“hp”]value = character.hp

__index 에서 멤버 함수 functor 를 리턴하면 멤버 함수로 호출이 가능하다 .-- functor 는 this 포인터를 모르므로 첫번째 인자로 개체 자체를 넘겨준다 .character.run(character)-- : 오퍼레이터는 이러한 작업을 단순화 시켜준다 .character:run()

Page 94: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

메타테이블 __newindex, __gc __newindex : table 에 접근하여 어떠한 값을

갱신하거나 써 넣을때 사용된다 . character[“hp”] = value character.hp = value

__gc : 메모리가 해지될때의 이벤트로 lua_tinker::destroyer() 가 불린다 .

template<typename T> int destroyer(lua_State *L) { /* user 객체로 타잎캐스팅 후 삭제하므로 virtual 함수가 호출된

다 . */ ((user*)lua_touserdata(L, 1))->~user(); return 0;

}

Page 95: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

LuaTinker 의 목표

Lua 버젼에 따라 계속적인 업데이트 동적 할당되는 메모리를 줄이고 포인터로 작동

하여 가벼움 유지 Table 접근이나 전역 변수 접근 기능 강화 .

Page 96: Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

LuaTinker Q&A