Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

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

description

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

Transcript of Kgc2006 Template Metaprogramming을 이용한 LuaTinker 구현

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